summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJin Qian2017-03-15 21:03:06 -0500
committerJin Qian2017-03-16 18:12:55 -0500
commit4fc338e60bf1d85212f1540d109beb1b248c4830 (patch)
tree0c2911d0119f8dcec09a81cda517895b319a4030 /storaged
parentbb82a5a53c437a778ae4a090f7bca7f76f86bc0c (diff)
downloadplatform-system-core-4fc338e60bf1d85212f1540d109beb1b248c4830.tar.gz
platform-system-core-4fc338e60bf1d85212f1540d109beb1b248c4830.tar.xz
platform-system-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)
16 16
17LOCAL_SRC_FILES := \ 17LOCAL_SRC_FILES := \
18 storaged.cpp \ 18 storaged.cpp \
19 storaged_info.cpp \
19 storaged_service.cpp \ 20 storaged_service.cpp \
20 storaged_utils.cpp \ 21 storaged_utils.cpp \
21 storaged_uid_monitor.cpp \ 22 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 @@
28 28
29#include <batteryservice/IBatteryPropertiesListener.h> 29#include <batteryservice/IBatteryPropertiesListener.h>
30 30
31#include "storaged_info.h"
31#include "storaged_uid_monitor.h" 32#include "storaged_uid_monitor.h"
32 33
33using namespace android; 34using namespace android;
@@ -44,6 +45,8 @@ friend class test_case_name##_##test_name##_Test
44#define debuginfo(...) 45#define debuginfo(...)
45#endif 46#endif
46 47
48#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
49
47#define SECTOR_SIZE ( 512 ) 50#define SECTOR_SIZE ( 512 )
48#define SEC_TO_MSEC ( 1000 ) 51#define SEC_TO_MSEC ( 1000 )
49#define MSEC_TO_USEC ( 1000 ) 52#define MSEC_TO_USEC ( 1000 )
@@ -83,15 +86,7 @@ struct disk_stats {
83 double io_avg; // average io_in_flight for accumulate calculations 86 double io_avg; // average io_in_flight for accumulate calculations
84}; 87};
85 88
86#define MMC_VER_STR_LEN ( 9 ) // maximum length of the MMC version string, including NULL terminator 89
87// minimum size of a ext_csd file
88#define EXT_CSD_FILE_MIN_SIZE ( 1024 )
89struct emmc_info {
90 int eol; // pre-eol (end of life) information
91 int lifetime_a; // device life time estimation (type A)
92 int lifetime_b; // device life time estimation (type B)
93 char mmc_ver[MMC_VER_STR_LEN]; // device version string
94};
95 90
96struct disk_perf { 91struct disk_perf {
97 uint32_t read_perf; // read speed (kbytes/s) 92 uint32_t read_perf; // read speed (kbytes/s)
@@ -232,26 +227,6 @@ public:
232 void update(void); 227 void update(void);
233}; 228};
234 229
235class emmc_info_t {
236private:
237 struct emmc_info mInfo;
238 bool mValid;
239 int mFdEmmc;
240public:
241 emmc_info_t(void) :
242 mValid(false),
243 mFdEmmc(-1) {
244 memset(&mInfo, 0, sizeof(struct emmc_info));
245 }
246 ~emmc_info_t(void) {}
247
248 void publish(void);
249 void update(void);
250 void set_emmc_fd(int fd) {
251 mFdEmmc = fd;
252 }
253};
254
255// Periodic chores intervals in seconds 230// Periodic chores intervals in seconds
256#define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 ) 231#define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 )
257#define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 ) 232#define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 )
@@ -268,7 +243,6 @@ struct storaged_config {
268 int periodic_chores_interval_emmc_info_publish; 243 int periodic_chores_interval_emmc_info_publish;
269 int periodic_chores_interval_uid_io; 244 int periodic_chores_interval_uid_io;
270 bool proc_uid_io_available; // whether uid_io is accessible 245 bool proc_uid_io_available; // whether uid_io is accessible
271 bool emmc_available; // whether eMMC est_csd file is readable
272 bool diskstats_available; // whether diskstats is accessible 246 bool diskstats_available; // whether diskstats is accessible
273 int event_time_check_usec; // check how much cputime spent in event loop 247 int event_time_check_usec; // check how much cputime spent in event loop
274}; 248};
@@ -279,7 +253,7 @@ private:
279 storaged_config mConfig; 253 storaged_config mConfig;
280 disk_stats_publisher mDiskStats; 254 disk_stats_publisher mDiskStats;
281 disk_stats_monitor mDsm; 255 disk_stats_monitor mDsm;
282 emmc_info_t mEmmcInfo; 256 storage_info_t *info = nullptr;
283 uid_monitor mUidm; 257 uid_monitor mUidm;
284 time_t mStarttime; 258 time_t mStarttime;
285public: 259public:
@@ -290,8 +264,8 @@ public:
290 void pause(void) { 264 void pause(void) {
291 sleep(mConfig.periodic_chores_interval_unit); 265 sleep(mConfig.periodic_chores_interval_unit);
292 } 266 }
293 void set_privileged_fds(int fd_emmc) { 267 void set_storage_info(storage_info_t *storage_info) {
294 mEmmcInfo.set_emmc_fd(fd_emmc); 268 info = storage_info;
295 } 269 }
296 270
297 time_t get_starttime(void) { 271 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 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _STORAGED_INFO_H_
18#define _STORAGED_INFO_H_
19
20#include <string.h>
21
22#define FRIEND_TEST(test_case_name, test_name) \
23friend class test_case_name##_##test_name##_Test
24
25using namespace std;
26
27// two characters in string for each byte
28struct str_hex {
29 char str[2];
30};
31
32class storage_info_t {
33protected:
34 FRIEND_TEST(storaged_test, storage_info_t);
35 uint8_t eol; // pre-eol (end of life) information
36 uint8_t lifetime_a; // device life time estimation (type A)
37 uint8_t lifetime_b; // device life time estimation (type B)
38 string version; // version string
39public:
40 void publish();
41 virtual ~storage_info_t() {}
42 virtual bool init() = 0;
43 virtual bool update() = 0;
44};
45
46class emmc_info_t : public storage_info_t {
47private:
48 // minimum size of a ext_csd file
49 const int EXT_CSD_FILE_MIN_SIZE = 1024;
50 // List of interesting offsets
51 const size_t EXT_CSD_REV_IDX = 192 * sizeof(str_hex);
52 const size_t EXT_PRE_EOL_INFO_IDX = 267 * sizeof(str_hex);
53 const size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * sizeof(str_hex);
54 const size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * sizeof(str_hex);
55
56 const char* ext_csd_file = "/d/mmc0/mmc0:0001/ext_csd";
57 const char* emmc_ver_str[8] = {
58 "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
59 };
60public:
61 virtual ~emmc_info_t() {}
62 bool init();
63 bool update();
64};
65
66#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 @@
43#include <storaged_utils.h> 43#include <storaged_utils.h>
44 44
45storaged_t storaged; 45storaged_t storaged;
46emmc_info_t emmc_info;
46 47
47// Function of storaged's main thread 48// Function of storaged's main thread
48void* storaged_main(void* s) { 49void* storaged_main(void* s) {
@@ -69,7 +70,6 @@ static void help_message(void) {
69int main(int argc, char** argv) { 70int main(int argc, char** argv) {
70 int flag_main_service = 0; 71 int flag_main_service = 0;
71 int flag_dump_uid = 0; 72 int flag_dump_uid = 0;
72 int fd_emmc = -1;
73 int opt; 73 int opt;
74 74
75 for (;;) { 75 for (;;) {
@@ -114,12 +114,9 @@ int main(int argc, char** argv) {
114 } 114 }
115 115
116 if (flag_main_service) { // start main thread 116 if (flag_main_service) { // start main thread
117 static const char mmc0_ext_csd[] = "/d/mmc0/mmc0:0001/ext_csd"; 117 if (emmc_info.init()) {
118 fd_emmc = android_get_control_file(mmc0_ext_csd); 118 storaged.set_storage_info(&emmc_info);
119 if (fd_emmc < 0) 119 }
120 fd_emmc = TEMP_FAILURE_RETRY(open(mmc0_ext_csd, O_RDONLY));
121
122 storaged.set_privileged_fds(fd_emmc);
123 120
124 // Start the main thread of storaged 121 // Start the main thread of storaged
125 pthread_t storaged_main_thread; 122 pthread_t storaged_main_thread;
@@ -134,8 +131,6 @@ int main(int argc, char** argv) {
134 IPCThreadState::self()->joinThreadPool(); 131 IPCThreadState::self()->joinThreadPool();
135 pthread_join(storaged_main_thread, NULL); 132 pthread_join(storaged_main_thread, NULL);
136 133
137 close(fd_emmc);
138
139 return 0; 134 return 0;
140 } 135 }
141 136
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) {
147 } 147 }
148} 148}
149 149
150/* emmc_info_t */
151void emmc_info_t::publish(void) {
152 if (mValid) {
153 log_event_emmc_info(&mInfo);
154 }
155}
156
157void emmc_info_t::update(void) {
158 if (mFdEmmc >= 0) {
159 mValid = parse_emmc_ecsd(mFdEmmc, &mInfo);
160 }
161}
162
163static sp<IBatteryPropertiesRegistrar> get_battery_properties_service() { 150static sp<IBatteryPropertiesRegistrar> get_battery_properties_service() {
164 sp<IServiceManager> sm = defaultServiceManager(); 151 sp<IServiceManager> sm = defaultServiceManager();
165 if (sm == NULL) return NULL; 152 if (sm == NULL) return NULL;
@@ -199,8 +186,6 @@ void storaged_t::init_battery_service() {
199 186
200/* storaged_t */ 187/* storaged_t */
201storaged_t::storaged_t(void) { 188storaged_t::storaged_t(void) {
202 mConfig.emmc_available = (access(EMMC_ECSD_PATH, R_OK) >= 0);
203
204 if (access(MMC_DISK_STATS_PATH, R_OK) < 0 && access(SDA_DISK_STATS_PATH, R_OK) < 0) { 189 if (access(MMC_DISK_STATS_PATH, R_OK) < 0 && access(SDA_DISK_STATS_PATH, R_OK) < 0) {
205 mConfig.diskstats_available = false; 190 mConfig.diskstats_available = false;
206 } else { 191 } else {
@@ -236,10 +221,10 @@ void storaged_t::event(void) {
236 } 221 }
237 } 222 }
238 223
239 if (mConfig.emmc_available && mTimer && 224 if (info && mTimer &&
240 (mTimer % mConfig.periodic_chores_interval_emmc_info_publish) == 0) { 225 (mTimer % mConfig.periodic_chores_interval_emmc_info_publish) == 0) {
241 mEmmcInfo.update(); 226 info->update();
242 mEmmcInfo.publish(); 227 info->publish();
243 } 228 }
244 229
245 if (mConfig.proc_uid_io_available && mTimer && 230 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 @@
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "storaged"
18
19#include <string.h>
20
21#include <android-base/file.h>
22#include <android-base/logging.h>
23#include <android-base/parseint.h>
24#include <log/log_event_list.h>
25
26#include "storaged.h"
27
28using namespace std;
29using namespace android;
30using namespace android::base;
31
32void storage_info_t::publish()
33{
34 if (eol == 0 && lifetime_a == 0 && lifetime_b == 0) {
35 return;
36 }
37
38 android_log_event_list(EVENTLOGTAG_EMMCINFO)
39 << version << eol << lifetime_a << lifetime_b
40 << LOG_ID_EVENTS;
41}
42
43bool emmc_info_t::init()
44{
45 string buffer;
46 if (!ReadFileToString(ext_csd_file, &buffer) ||
47 buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) {
48 return false;
49 }
50
51 string ver_str = buffer.substr(EXT_CSD_REV_IDX, sizeof(str_hex));
52 uint8_t ext_csd_rev;
53 if (!ParseUint(ver_str, &ext_csd_rev)) {
54 LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_CSD_REV.";
55 return false;
56 }
57
58 version = "emmc ";
59 version += (ext_csd_rev < ARRAY_SIZE(emmc_ver_str)) ?
60 emmc_ver_str[ext_csd_rev] : "Unknown";
61
62 if (ext_csd_rev < 7) {
63 return false;
64 }
65
66 return update();
67}
68
69bool emmc_info_t::update()
70{
71 string buffer;
72 if (!ReadFileToString(ext_csd_file, &buffer) ||
73 buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) {
74 return false;
75 }
76
77 string str = buffer.substr(EXT_PRE_EOL_INFO_IDX, sizeof(str_hex));
78 if (!ParseUint(str, &eol)) {
79 LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_PRE_EOL_INFO.";
80 return false;
81 }
82
83 str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, sizeof(str_hex));
84 if (!ParseUint(str, &lifetime_a)) {
85 LOG_TO(SYSTEM, ERROR)
86 << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_A.";
87 return false;
88 }
89
90 str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, sizeof(str_hex));
91 if (!ParseUint(str, &lifetime_b)) {
92 LOG_TO(SYSTEM, ERROR)
93 << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_B.";
94 return false;
95 }
96
97 return true;
98}
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) {
158 } 158 }
159} 159}
160 160
161bool parse_emmc_ecsd(int ext_csd_fd, struct emmc_info* info) {
162 CHECK(ext_csd_fd >= 0);
163 struct hex {
164 char str[2];
165 };
166 // List of interesting offsets
167 static const size_t EXT_CSD_REV_IDX = 192 * sizeof(hex);
168 static const size_t EXT_PRE_EOL_INFO_IDX = 267 * sizeof(hex);
169 static const size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * sizeof(hex);
170 static const size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * sizeof(hex);
171
172 // Read file
173 CHECK(lseek(ext_csd_fd, 0, SEEK_SET) == 0);
174 std::string buffer;
175 if (!android::base::ReadFdToString(ext_csd_fd, &buffer)) {
176 PLOG_TO(SYSTEM, ERROR) << "ReadFdToString failed.";
177 return false;
178 }
179
180 if (buffer.length() < EXT_CSD_FILE_MIN_SIZE) {
181 LOG_TO(SYSTEM, ERROR) << "EMMC ext csd file has truncated content. "
182 << "File length: " << buffer.length();
183 return false;
184 }
185
186 std::string sub;
187 std::stringstream ss;
188 // Parse EXT_CSD_REV
189 int ext_csd_rev = -1;
190 sub = buffer.substr(EXT_CSD_REV_IDX, sizeof(hex));
191 ss << sub;
192 ss >> std::hex >> ext_csd_rev;
193 if (ext_csd_rev < 0) {
194 LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_CSD_REV.";
195 return false;
196 }
197 ss.clear();
198
199 static const char* ver_str[] = {
200 "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
201 };
202
203 strlcpy(info->mmc_ver,
204 (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ?
205 ver_str[ext_csd_rev] :
206 "Unknown",
207 MMC_VER_STR_LEN);
208
209 if (ext_csd_rev < 7) {
210 return 0;
211 }
212
213 // Parse EXT_PRE_EOL_INFO
214 info->eol = -1;
215 sub = buffer.substr(EXT_PRE_EOL_INFO_IDX, sizeof(hex));
216 ss << sub;
217 ss >> std::hex >> info->eol;
218 if (info->eol < 0) {
219 LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_PRE_EOL_INFO.";
220 return false;
221 }
222 ss.clear();
223
224 // Parse DEVICE_LIFE_TIME_EST
225 info->lifetime_a = -1;
226 sub = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, sizeof(hex));
227 ss << sub;
228 ss >> std::hex >> info->lifetime_a;
229 if (info->lifetime_a < 0) {
230 LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_A.";
231 return false;
232 }
233 ss.clear();
234
235 info->lifetime_b = -1;
236 sub = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, sizeof(hex));
237 ss << sub;
238 ss >> std::hex >> info->lifetime_b;
239 if (info->lifetime_b < 0) {
240 LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_B.";
241 return false;
242 }
243 ss.clear();
244
245 return true;
246}
247
248static bool cmp_uid_info(struct uid_info l, struct uid_info r) { 161static bool cmp_uid_info(struct uid_info l, struct uid_info r) {
249 // Compare background I/O first. 162 // Compare background I/O first.
250 for (int i = UID_STATS - 1; i >= 0; i--) { 163 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) {
317 << LOG_ID_EVENTS; 230 << LOG_ID_EVENTS;
318} 231}
319 232
320void log_event_emmc_info(struct emmc_info* info) {
321 // skip if the input structure are all zeros
322 if (info == NULL) return;
323 struct emmc_info zero_cmp;
324 memset(&zero_cmp, 0, sizeof(zero_cmp));
325 if (memcmp(&zero_cmp, info, sizeof(struct emmc_info)) == 0) return;
326
327 android_log_event_list(EVENTLOGTAG_EMMCINFO)
328 << info->mmc_ver << info->eol << info->lifetime_a << info->lifetime_b
329 << LOG_ID_EVENTS;
330}
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) {
58const char* DISK_STATS_PATH; 58const char* DISK_STATS_PATH;
59TEST(storaged_test, retvals) { 59TEST(storaged_test, retvals) {
60 struct disk_stats stats; 60 struct disk_stats stats;
61 struct emmc_info info; 61 emmc_info_t info;
62 memset(&stats, 0, sizeof(struct disk_stats)); 62 memset(&stats, 0, sizeof(struct disk_stats));
63 memset(&info, 0, sizeof(struct emmc_info));
64 63
65 int emmc_fd = open(EMMC_EXT_CSD_PATH, O_RDONLY); 64 if (info.init()) {
66 if (emmc_fd >= 0) { 65 EXPECT_TRUE(info.update());
67 EXPECT_TRUE(parse_emmc_ecsd(emmc_fd, &info));
68 } 66 }
69 67
70 if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) { 68 if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) {
@@ -129,17 +127,17 @@ TEST(storaged_test, disk_stats) {
129 } 127 }
130} 128}
131 129
132TEST(storaged_test, emmc_info) { 130TEST(storaged_test, storage_info_t) {
133 struct emmc_info info, void_info; 131 emmc_info_t info;
134 memset(&info, 0, sizeof(struct emmc_info));
135 memset(&void_info, 0, sizeof(struct emmc_info));
136 132
137 if (access(EMMC_EXT_CSD_PATH, R_OK) >= 0) { 133 if (access(EMMC_EXT_CSD_PATH, R_OK) >= 0) {
138 int emmc_fd = open(EMMC_EXT_CSD_PATH, O_RDONLY); 134 int ret = info.init();
139 ASSERT_GE(emmc_fd, 0); 135 if (ret) {
140 ASSERT_TRUE(parse_emmc_ecsd(emmc_fd, &info)); 136 EXPECT_TRUE(info.version.empty());
141 // parse_emmc_ecsd() should put something in info. 137 ASSERT_TRUE(info.update());
142 EXPECT_NE(0, memcmp(&void_info, &info, sizeof(struct emmc_info))); 138 // update should put something in info.
139 EXPECT_TRUE(info.eol || info.lifetime_a || info.lifetime_b);
140 }
143 } 141 }
144} 142}
145 143