diff options
author | Jin Qian <jinqian@google.com> | 2017-03-15 19:03:06 -0700 |
---|---|---|
committer | Jin Qian <jinqian@google.com> | 2017-03-16 16:12:55 -0700 |
commit | 4fc338e60bf1d85212f1540d109beb1b248c4830 (patch) | |
tree | 0c2911d0119f8dcec09a81cda517895b319a4030 /storaged | |
parent | bb82a5a53c437a778ae4a090f7bca7f76f86bc0c (diff) | |
download | core-4fc338e60bf1d85212f1540d109beb1b248c4830.tar.gz core-4fc338e60bf1d85212f1540d109beb1b248c4830.tar.bz2 core-4fc338e60bf1d85212f1540d109beb1b248c4830.zip |
storaged: rewrite emmc info class
Test: adb logcat -d -b events | grep storaged_emmc_info
Bug: 36228467
Change-Id: Ib799e60ed65661a9fb99be8ad4c930f547339975
Diffstat (limited to 'storaged')
-rw-r--r-- | storaged/Android.mk | 1 | ||||
-rw-r--r-- | storaged/include/storaged.h | 40 | ||||
-rw-r--r-- | storaged/include/storaged_info.h | 66 | ||||
-rw-r--r-- | storaged/main.cpp | 13 | ||||
-rw-r--r-- | storaged/storaged.cpp | 23 | ||||
-rw-r--r-- | storaged/storaged_info.cpp | 98 | ||||
-rw-r--r-- | storaged/storaged_utils.cpp | 98 | ||||
-rw-r--r-- | storaged/tests/storaged_test.cpp | 26 |
8 files changed, 192 insertions, 173 deletions
diff --git a/storaged/Android.mk b/storaged/Android.mk index 2adb14daa..5e6a3c0a1 100644 --- a/storaged/Android.mk +++ b/storaged/Android.mk @@ -16,6 +16,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ storaged.cpp \ + storaged_info.cpp \ storaged_service.cpp \ storaged_utils.cpp \ storaged_uid_monitor.cpp \ diff --git a/storaged/include/storaged.h b/storaged/include/storaged.h index c291bd98c..bd1391c98 100644 --- a/storaged/include/storaged.h +++ b/storaged/include/storaged.h @@ -28,6 +28,7 @@ #include <batteryservice/IBatteryPropertiesListener.h> +#include "storaged_info.h" #include "storaged_uid_monitor.h" using namespace android; @@ -44,6 +45,8 @@ friend class test_case_name##_##test_name##_Test #define debuginfo(...) #endif +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + #define SECTOR_SIZE ( 512 ) #define SEC_TO_MSEC ( 1000 ) #define MSEC_TO_USEC ( 1000 ) @@ -83,15 +86,7 @@ struct disk_stats { double io_avg; // average io_in_flight for accumulate calculations }; -#define MMC_VER_STR_LEN ( 9 ) // maximum length of the MMC version string, including NULL terminator -// minimum size of a ext_csd file -#define EXT_CSD_FILE_MIN_SIZE ( 1024 ) -struct emmc_info { - int eol; // pre-eol (end of life) information - int lifetime_a; // device life time estimation (type A) - int lifetime_b; // device life time estimation (type B) - char mmc_ver[MMC_VER_STR_LEN]; // device version string -}; + struct disk_perf { uint32_t read_perf; // read speed (kbytes/s) @@ -232,26 +227,6 @@ public: void update(void); }; -class emmc_info_t { -private: - struct emmc_info mInfo; - bool mValid; - int mFdEmmc; -public: - emmc_info_t(void) : - mValid(false), - mFdEmmc(-1) { - memset(&mInfo, 0, sizeof(struct emmc_info)); - } - ~emmc_info_t(void) {} - - void publish(void); - void update(void); - void set_emmc_fd(int fd) { - mFdEmmc = fd; - } -}; - // Periodic chores intervals in seconds #define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 ) #define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 ) @@ -268,7 +243,6 @@ struct storaged_config { int periodic_chores_interval_emmc_info_publish; int periodic_chores_interval_uid_io; bool proc_uid_io_available; // whether uid_io is accessible - bool emmc_available; // whether eMMC est_csd file is readable bool diskstats_available; // whether diskstats is accessible int event_time_check_usec; // check how much cputime spent in event loop }; @@ -279,7 +253,7 @@ private: storaged_config mConfig; disk_stats_publisher mDiskStats; disk_stats_monitor mDsm; - emmc_info_t mEmmcInfo; + storage_info_t *info = nullptr; uid_monitor mUidm; time_t mStarttime; public: @@ -290,8 +264,8 @@ public: void pause(void) { sleep(mConfig.periodic_chores_interval_unit); } - void set_privileged_fds(int fd_emmc) { - mEmmcInfo.set_emmc_fd(fd_emmc); + void set_storage_info(storage_info_t *storage_info) { + info = storage_info; } time_t get_starttime(void) { diff --git a/storaged/include/storaged_info.h b/storaged/include/storaged_info.h new file mode 100644 index 000000000..cb5b8a8e2 --- /dev/null +++ b/storaged/include/storaged_info.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _STORAGED_INFO_H_ +#define _STORAGED_INFO_H_ + +#include <string.h> + +#define FRIEND_TEST(test_case_name, test_name) \ +friend class test_case_name##_##test_name##_Test + +using namespace std; + +// two characters in string for each byte +struct str_hex { + char str[2]; +}; + +class storage_info_t { +protected: + FRIEND_TEST(storaged_test, storage_info_t); + uint8_t eol; // pre-eol (end of life) information + uint8_t lifetime_a; // device life time estimation (type A) + uint8_t lifetime_b; // device life time estimation (type B) + string version; // version string +public: + void publish(); + virtual ~storage_info_t() {} + virtual bool init() = 0; + virtual bool update() = 0; +}; + +class emmc_info_t : public storage_info_t { +private: + // minimum size of a ext_csd file + const int EXT_CSD_FILE_MIN_SIZE = 1024; + // List of interesting offsets + const size_t EXT_CSD_REV_IDX = 192 * sizeof(str_hex); + const size_t EXT_PRE_EOL_INFO_IDX = 267 * sizeof(str_hex); + const size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * sizeof(str_hex); + const size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * sizeof(str_hex); + + const char* ext_csd_file = "/d/mmc0/mmc0:0001/ext_csd"; + const char* emmc_ver_str[8] = { + "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0" + }; +public: + virtual ~emmc_info_t() {} + bool init(); + bool update(); +}; + +#endif /* _STORAGED_INFO_H_ */ diff --git a/storaged/main.cpp b/storaged/main.cpp index 672f453b3..e25298b12 100644 --- a/storaged/main.cpp +++ b/storaged/main.cpp @@ -43,6 +43,7 @@ #include <storaged_utils.h> storaged_t storaged; +emmc_info_t emmc_info; // Function of storaged's main thread void* storaged_main(void* s) { @@ -69,7 +70,6 @@ static void help_message(void) { int main(int argc, char** argv) { int flag_main_service = 0; int flag_dump_uid = 0; - int fd_emmc = -1; int opt; for (;;) { @@ -114,12 +114,9 @@ int main(int argc, char** argv) { } if (flag_main_service) { // start main thread - static const char mmc0_ext_csd[] = "/d/mmc0/mmc0:0001/ext_csd"; - fd_emmc = android_get_control_file(mmc0_ext_csd); - if (fd_emmc < 0) - fd_emmc = TEMP_FAILURE_RETRY(open(mmc0_ext_csd, O_RDONLY)); - - storaged.set_privileged_fds(fd_emmc); + if (emmc_info.init()) { + storaged.set_storage_info(&emmc_info); + } // Start the main thread of storaged pthread_t storaged_main_thread; @@ -134,8 +131,6 @@ int main(int argc, char** argv) { IPCThreadState::self()->joinThreadPool(); pthread_join(storaged_main_thread, NULL); - close(fd_emmc); - return 0; } diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp index 2f020742a..88fbb7a3c 100644 --- a/storaged/storaged.cpp +++ b/storaged/storaged.cpp @@ -147,19 +147,6 @@ void disk_stats_monitor::update(void) { } } -/* emmc_info_t */ -void emmc_info_t::publish(void) { - if (mValid) { - log_event_emmc_info(&mInfo); - } -} - -void emmc_info_t::update(void) { - if (mFdEmmc >= 0) { - mValid = parse_emmc_ecsd(mFdEmmc, &mInfo); - } -} - static sp<IBatteryPropertiesRegistrar> get_battery_properties_service() { sp<IServiceManager> sm = defaultServiceManager(); if (sm == NULL) return NULL; @@ -199,8 +186,6 @@ void storaged_t::init_battery_service() { /* storaged_t */ storaged_t::storaged_t(void) { - mConfig.emmc_available = (access(EMMC_ECSD_PATH, R_OK) >= 0); - if (access(MMC_DISK_STATS_PATH, R_OK) < 0 && access(SDA_DISK_STATS_PATH, R_OK) < 0) { mConfig.diskstats_available = false; } else { @@ -236,10 +221,10 @@ void storaged_t::event(void) { } } - if (mConfig.emmc_available && mTimer && - (mTimer % mConfig.periodic_chores_interval_emmc_info_publish) == 0) { - mEmmcInfo.update(); - mEmmcInfo.publish(); + if (info && mTimer && + (mTimer % mConfig.periodic_chores_interval_emmc_info_publish) == 0) { + info->update(); + info->publish(); } if (mConfig.proc_uid_io_available && mTimer && diff --git a/storaged/storaged_info.cpp b/storaged/storaged_info.cpp new file mode 100644 index 000000000..73d611c04 --- /dev/null +++ b/storaged/storaged_info.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "storaged" + +#include <string.h> + +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/parseint.h> +#include <log/log_event_list.h> + +#include "storaged.h" + +using namespace std; +using namespace android; +using namespace android::base; + +void storage_info_t::publish() +{ + if (eol == 0 && lifetime_a == 0 && lifetime_b == 0) { + return; + } + + android_log_event_list(EVENTLOGTAG_EMMCINFO) + << version << eol << lifetime_a << lifetime_b + << LOG_ID_EVENTS; +} + +bool emmc_info_t::init() +{ + string buffer; + if (!ReadFileToString(ext_csd_file, &buffer) || + buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) { + return false; + } + + string ver_str = buffer.substr(EXT_CSD_REV_IDX, sizeof(str_hex)); + uint8_t ext_csd_rev; + if (!ParseUint(ver_str, &ext_csd_rev)) { + LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_CSD_REV."; + return false; + } + + version = "emmc "; + version += (ext_csd_rev < ARRAY_SIZE(emmc_ver_str)) ? + emmc_ver_str[ext_csd_rev] : "Unknown"; + + if (ext_csd_rev < 7) { + return false; + } + + return update(); +} + +bool emmc_info_t::update() +{ + string buffer; + if (!ReadFileToString(ext_csd_file, &buffer) || + buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) { + return false; + } + + string str = buffer.substr(EXT_PRE_EOL_INFO_IDX, sizeof(str_hex)); + if (!ParseUint(str, &eol)) { + LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_PRE_EOL_INFO."; + return false; + } + + str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, sizeof(str_hex)); + if (!ParseUint(str, &lifetime_a)) { + LOG_TO(SYSTEM, ERROR) + << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_A."; + return false; + } + + str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, sizeof(str_hex)); + if (!ParseUint(str, &lifetime_b)) { + LOG_TO(SYSTEM, ERROR) + << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_B."; + return false; + } + + return true; +} diff --git a/storaged/storaged_utils.cpp b/storaged/storaged_utils.cpp index 9fcf1fa8a..74b743656 100644 --- a/storaged/storaged_utils.cpp +++ b/storaged/storaged_utils.cpp @@ -158,93 +158,6 @@ void add_disk_stats(struct disk_stats* src, struct disk_stats* dst) { } } -bool parse_emmc_ecsd(int ext_csd_fd, struct emmc_info* info) { - CHECK(ext_csd_fd >= 0); - struct hex { - char str[2]; - }; - // List of interesting offsets - static const size_t EXT_CSD_REV_IDX = 192 * sizeof(hex); - static const size_t EXT_PRE_EOL_INFO_IDX = 267 * sizeof(hex); - static const size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * sizeof(hex); - static const size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * sizeof(hex); - - // Read file - CHECK(lseek(ext_csd_fd, 0, SEEK_SET) == 0); - std::string buffer; - if (!android::base::ReadFdToString(ext_csd_fd, &buffer)) { - PLOG_TO(SYSTEM, ERROR) << "ReadFdToString failed."; - return false; - } - - if (buffer.length() < EXT_CSD_FILE_MIN_SIZE) { - LOG_TO(SYSTEM, ERROR) << "EMMC ext csd file has truncated content. " - << "File length: " << buffer.length(); - return false; - } - - std::string sub; - std::stringstream ss; - // Parse EXT_CSD_REV - int ext_csd_rev = -1; - sub = buffer.substr(EXT_CSD_REV_IDX, sizeof(hex)); - ss << sub; - ss >> std::hex >> ext_csd_rev; - if (ext_csd_rev < 0) { - LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_CSD_REV."; - return false; - } - ss.clear(); - - static const char* ver_str[] = { - "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0" - }; - - strlcpy(info->mmc_ver, - (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ? - ver_str[ext_csd_rev] : - "Unknown", - MMC_VER_STR_LEN); - - if (ext_csd_rev < 7) { - return 0; - } - - // Parse EXT_PRE_EOL_INFO - info->eol = -1; - sub = buffer.substr(EXT_PRE_EOL_INFO_IDX, sizeof(hex)); - ss << sub; - ss >> std::hex >> info->eol; - if (info->eol < 0) { - LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_PRE_EOL_INFO."; - return false; - } - ss.clear(); - - // Parse DEVICE_LIFE_TIME_EST - info->lifetime_a = -1; - sub = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, sizeof(hex)); - ss << sub; - ss >> std::hex >> info->lifetime_a; - if (info->lifetime_a < 0) { - LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_A."; - return false; - } - ss.clear(); - - info->lifetime_b = -1; - sub = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, sizeof(hex)); - ss << sub; - ss >> std::hex >> info->lifetime_b; - if (info->lifetime_b < 0) { - LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_B."; - return false; - } - ss.clear(); - - return true; -} - static bool cmp_uid_info(struct uid_info l, struct uid_info r) { // Compare background I/O first. for (int i = UID_STATS - 1; i >= 0; i--) { @@ -317,14 +230,3 @@ void log_event_disk_stats(struct disk_stats* stats, const char* type) { << LOG_ID_EVENTS; } -void log_event_emmc_info(struct emmc_info* info) { - // skip if the input structure are all zeros - if (info == NULL) return; - struct emmc_info zero_cmp; - memset(&zero_cmp, 0, sizeof(zero_cmp)); - if (memcmp(&zero_cmp, info, sizeof(struct emmc_info)) == 0) return; - - android_log_event_list(EVENTLOGTAG_EMMCINFO) - << info->mmc_ver << info->eol << info->lifetime_a << info->lifetime_b - << LOG_ID_EVENTS; -} diff --git a/storaged/tests/storaged_test.cpp b/storaged/tests/storaged_test.cpp index 9e03c5018..e335cad87 100644 --- a/storaged/tests/storaged_test.cpp +++ b/storaged/tests/storaged_test.cpp @@ -58,13 +58,11 @@ static void pause(uint32_t sec) { const char* DISK_STATS_PATH; TEST(storaged_test, retvals) { struct disk_stats stats; - struct emmc_info info; + emmc_info_t info; memset(&stats, 0, sizeof(struct disk_stats)); - memset(&info, 0, sizeof(struct emmc_info)); - int emmc_fd = open(EMMC_EXT_CSD_PATH, O_RDONLY); - if (emmc_fd >= 0) { - EXPECT_TRUE(parse_emmc_ecsd(emmc_fd, &info)); + if (info.init()) { + EXPECT_TRUE(info.update()); } if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) { @@ -129,17 +127,17 @@ TEST(storaged_test, disk_stats) { } } -TEST(storaged_test, emmc_info) { - struct emmc_info info, void_info; - memset(&info, 0, sizeof(struct emmc_info)); - memset(&void_info, 0, sizeof(struct emmc_info)); +TEST(storaged_test, storage_info_t) { + emmc_info_t info; if (access(EMMC_EXT_CSD_PATH, R_OK) >= 0) { - int emmc_fd = open(EMMC_EXT_CSD_PATH, O_RDONLY); - ASSERT_GE(emmc_fd, 0); - ASSERT_TRUE(parse_emmc_ecsd(emmc_fd, &info)); - // parse_emmc_ecsd() should put something in info. - EXPECT_NE(0, memcmp(&void_info, &info, sizeof(struct emmc_info))); + int ret = info.init(); + if (ret) { + EXPECT_TRUE(info.version.empty()); + ASSERT_TRUE(info.update()); + // update should put something in info. + EXPECT_TRUE(info.eol || info.lifetime_a || info.lifetime_b); + } } } |