summaryrefslogtreecommitdiffstats
path: root/storaged
diff options
context:
space:
mode:
authorJin Qian <jinqian@google.com>2017-03-15 19:03:06 -0700
committerJin Qian <jinqian@google.com>2017-03-16 16:12:55 -0700
commit4fc338e60bf1d85212f1540d109beb1b248c4830 (patch)
tree0c2911d0119f8dcec09a81cda517895b319a4030 /storaged
parentbb82a5a53c437a778ae4a090f7bca7f76f86bc0c (diff)
downloadcore-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.mk1
-rw-r--r--storaged/include/storaged.h40
-rw-r--r--storaged/include/storaged_info.h66
-rw-r--r--storaged/main.cpp13
-rw-r--r--storaged/storaged.cpp23
-rw-r--r--storaged/storaged_info.cpp98
-rw-r--r--storaged/storaged_utils.cpp98
-rw-r--r--storaged/tests/storaged_test.cpp26
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);
+ }
}
}