1 /*
2  * Copyright (C) 2013 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 "healthd"
18 
19 #include <healthd/healthd.h>
20 #include <healthd/BatteryMonitor.h>
21 
22 #include <dirent.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 
30 #include <algorithm>
31 #include <memory>
32 #include <optional>
33 
34 #include <aidl/android/hardware/health/HealthInfo.h>
35 #include <android-base/file.h>
36 #include <android-base/parseint.h>
37 #include <android-base/strings.h>
38 #include <android/hardware/health/2.1/types.h>
39 #include <android/hardware/health/translate-ndk.h>
40 #include <batteryservice/BatteryService.h>
41 #include <cutils/klog.h>
42 #include <cutils/properties.h>
43 #include <utils/Errors.h>
44 #include <utils/String8.h>
45 #include <utils/Vector.h>
46 
47 #define POWER_SUPPLY_SUBSYSTEM "power_supply"
48 #define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
49 #define FAKE_BATTERY_CAPACITY 42
50 #define FAKE_BATTERY_TEMPERATURE 424
51 #define MILLION 1.0e6
52 #define DEFAULT_VBUS_VOLTAGE 5000000
53 
54 using HealthInfo_1_0 = android::hardware::health::V1_0::HealthInfo;
55 using HealthInfo_2_0 = android::hardware::health::V2_0::HealthInfo;
56 using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
57 using aidl::android::hardware::health::BatteryCapacityLevel;
58 using aidl::android::hardware::health::BatteryChargingPolicy;
59 using aidl::android::hardware::health::BatteryChargingState;
60 using aidl::android::hardware::health::BatteryHealth;
61 using aidl::android::hardware::health::BatteryHealthData;
62 using aidl::android::hardware::health::BatteryStatus;
63 using aidl::android::hardware::health::HealthInfo;
64 
65 namespace {
66 
67 // Translate from AIDL back to HIDL definition for getHealthInfo_*_* calls.
68 // Skips storageInfo and diskStats.
translateToHidl(const::aidl::android::hardware::health::HealthInfo & in,::android::hardware::health::V1_0::HealthInfo * out)69 void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
70                      ::android::hardware::health::V1_0::HealthInfo* out) {
71     out->chargerAcOnline = in.chargerAcOnline;
72     out->chargerUsbOnline = in.chargerUsbOnline;
73     out->chargerWirelessOnline = in.chargerWirelessOnline;
74     out->maxChargingCurrent = in.maxChargingCurrentMicroamps;
75     out->maxChargingVoltage = in.maxChargingVoltageMicrovolts;
76     out->batteryStatus =
77             static_cast<::android::hardware::health::V1_0::BatteryStatus>(in.batteryStatus);
78     out->batteryHealth =
79             static_cast<::android::hardware::health::V1_0::BatteryHealth>(in.batteryHealth);
80     out->batteryPresent = in.batteryPresent;
81     out->batteryLevel = in.batteryLevel;
82     out->batteryVoltage = in.batteryVoltageMillivolts;
83     out->batteryTemperature = in.batteryTemperatureTenthsCelsius;
84     out->batteryCurrent = in.batteryCurrentMicroamps;
85     out->batteryCycleCount = in.batteryCycleCount;
86     out->batteryFullCharge = in.batteryFullChargeUah;
87     out->batteryChargeCounter = in.batteryChargeCounterUah;
88     out->batteryTechnology = in.batteryTechnology;
89 }
90 
translateToHidl(const::aidl::android::hardware::health::HealthInfo & in,::android::hardware::health::V2_0::HealthInfo * out)91 void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
92                      ::android::hardware::health::V2_0::HealthInfo* out) {
93     translateToHidl(in, &out->legacy);
94     out->batteryCurrentAverage = in.batteryCurrentAverageMicroamps;
95     // Skip storageInfo and diskStats
96 }
97 
translateToHidl(const::aidl::android::hardware::health::HealthInfo & in,::android::hardware::health::V2_1::HealthInfo * out)98 void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
99                      ::android::hardware::health::V2_1::HealthInfo* out) {
100     translateToHidl(in, &out->legacy);
101     out->batteryCapacityLevel = static_cast<android::hardware::health::V2_1::BatteryCapacityLevel>(
102             in.batteryCapacityLevel);
103     out->batteryChargeTimeToFullNowSeconds = in.batteryChargeTimeToFullNowSeconds;
104     out->batteryFullChargeDesignCapacityUah = in.batteryFullChargeDesignCapacityUah;
105 }
106 
107 }  // namespace
108 
109 namespace android {
110 
111 template <typename T>
112 struct SysfsStringEnumMap {
113     const char* s;
114     T val;
115 };
116 
117 template <typename T>
mapSysfsString(const char * str,SysfsStringEnumMap<T> map[])118 static std::optional<T> mapSysfsString(const char* str, SysfsStringEnumMap<T> map[]) {
119     for (int i = 0; map[i].s; i++)
120         if (!strcmp(str, map[i].s))
121             return map[i].val;
122 
123     return std::nullopt;
124 }
125 
initHealthInfo(HealthInfo * health_info)126 static void initHealthInfo(HealthInfo* health_info) {
127     *health_info = {
128             .batteryCapacityLevel = BatteryCapacityLevel::UNSUPPORTED,
129             .batteryChargeTimeToFullNowSeconds =
130                     (int64_t)HealthInfo::BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED,
131             .batteryStatus = BatteryStatus::UNKNOWN,
132             .batteryHealth = BatteryHealth::UNKNOWN,
133     };
134 }
135 
BatteryMonitor()136 BatteryMonitor::BatteryMonitor()
137     : mHealthdConfig(nullptr),
138       mBatteryDevicePresent(false),
139       mBatteryFixedCapacity(0),
140       mBatteryFixedTemperature(0),
141       mBatteryHealthStatus(BatteryMonitor::BH_UNKNOWN),
142       mHealthInfo(std::make_unique<HealthInfo>()) {
143     initHealthInfo(mHealthInfo.get());
144 }
145 
~BatteryMonitor()146 BatteryMonitor::~BatteryMonitor() {}
147 
getHealthInfo_1_0() const148 HealthInfo_1_0 BatteryMonitor::getHealthInfo_1_0() const {
149     HealthInfo_1_0 health_info_1_0;
150     translateToHidl(*mHealthInfo, &health_info_1_0);
151     return health_info_1_0;
152 }
153 
getHealthInfo_2_0() const154 HealthInfo_2_0 BatteryMonitor::getHealthInfo_2_0() const {
155     HealthInfo_2_0 health_info_2_0;
156     translateToHidl(*mHealthInfo, &health_info_2_0);
157     return health_info_2_0;
158 }
159 
getHealthInfo_2_1() const160 HealthInfo_2_1 BatteryMonitor::getHealthInfo_2_1() const {
161     HealthInfo_2_1 health_info_2_1;
162     translateToHidl(*mHealthInfo, &health_info_2_1);
163     return health_info_2_1;
164 }
165 
getHealthInfo() const166 const HealthInfo& BatteryMonitor::getHealthInfo() const {
167     return *mHealthInfo;
168 }
169 
getBatteryStatus(const char * status)170 BatteryStatus getBatteryStatus(const char* status) {
171     static SysfsStringEnumMap<BatteryStatus> batteryStatusMap[] = {
172             {"Unknown", BatteryStatus::UNKNOWN},
173             {"Charging", BatteryStatus::CHARGING},
174             {"Discharging", BatteryStatus::DISCHARGING},
175             {"Not charging", BatteryStatus::NOT_CHARGING},
176             {"Full", BatteryStatus::FULL},
177             {NULL, BatteryStatus::UNKNOWN},
178     };
179 
180     auto ret = mapSysfsString(status, batteryStatusMap);
181     if (!ret) {
182         KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
183         *ret = BatteryStatus::UNKNOWN;
184     }
185 
186     return *ret;
187 }
188 
getBatteryCapacityLevel(const char * capacityLevel)189 BatteryCapacityLevel getBatteryCapacityLevel(const char* capacityLevel) {
190     static SysfsStringEnumMap<BatteryCapacityLevel> batteryCapacityLevelMap[] = {
191             {"Unknown", BatteryCapacityLevel::UNKNOWN},
192             {"Critical", BatteryCapacityLevel::CRITICAL},
193             {"Low", BatteryCapacityLevel::LOW},
194             {"Normal", BatteryCapacityLevel::NORMAL},
195             {"High", BatteryCapacityLevel::HIGH},
196             {"Full", BatteryCapacityLevel::FULL},
197             {NULL, BatteryCapacityLevel::UNSUPPORTED},
198     };
199 
200     auto ret = mapSysfsString(capacityLevel, batteryCapacityLevelMap);
201     if (!ret) {
202         KLOG_WARNING(LOG_TAG, "Unsupported battery capacity level '%s'\n", capacityLevel);
203         *ret = BatteryCapacityLevel::UNSUPPORTED;
204     }
205 
206     return *ret;
207 }
208 
getBatteryHealth(const char * status)209 BatteryHealth getBatteryHealth(const char* status) {
210     static SysfsStringEnumMap<BatteryHealth> batteryHealthMap[] = {
211             {"Unknown", BatteryHealth::UNKNOWN},
212             {"Good", BatteryHealth::GOOD},
213             {"Overheat", BatteryHealth::OVERHEAT},
214             {"Dead", BatteryHealth::DEAD},
215             {"Over voltage", BatteryHealth::OVER_VOLTAGE},
216             {"Unspecified failure", BatteryHealth::UNSPECIFIED_FAILURE},
217             {"Cold", BatteryHealth::COLD},
218             // battery health values from JEITA spec
219             {"Warm", BatteryHealth::GOOD},
220             {"Cool", BatteryHealth::GOOD},
221             {"Hot", BatteryHealth::OVERHEAT},
222             {NULL, BatteryHealth::UNKNOWN},
223     };
224 
225     auto ret = mapSysfsString(status, batteryHealthMap);
226     if (!ret) {
227         KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
228         *ret = BatteryHealth::UNKNOWN;
229     }
230 
231     return *ret;
232 }
233 
getBatteryHealthStatus(int status)234 BatteryHealth getBatteryHealthStatus(int status) {
235     BatteryHealth value;
236 
237     if (status == BatteryMonitor::BH_NOMINAL)
238         value = BatteryHealth::GOOD;
239     else if (status == BatteryMonitor::BH_MARGINAL)
240         value = BatteryHealth::FAIR;
241     else if (status == BatteryMonitor::BH_NEEDS_REPLACEMENT)
242         value = BatteryHealth::DEAD;
243     else if (status == BatteryMonitor::BH_FAILED)
244         value = BatteryHealth::UNSPECIFIED_FAILURE;
245     else if (status == BatteryMonitor::BH_NOT_AVAILABLE)
246         value = BatteryHealth::NOT_AVAILABLE;
247     else if (status == BatteryMonitor::BH_INCONSISTENT)
248         value = BatteryHealth::INCONSISTENT;
249     else
250         value = BatteryHealth::UNKNOWN;
251 
252     return value;
253 }
254 
getBatteryChargingPolicy(const char * chargingPolicy)255 BatteryChargingPolicy getBatteryChargingPolicy(const char* chargingPolicy) {
256     static SysfsStringEnumMap<BatteryChargingPolicy> batteryChargingPolicyMap[] = {
257             {"0", BatteryChargingPolicy::INVALID},   {"1", BatteryChargingPolicy::DEFAULT},
258             {"2", BatteryChargingPolicy::LONG_LIFE}, {"3", BatteryChargingPolicy::ADAPTIVE},
259             {NULL, BatteryChargingPolicy::DEFAULT},
260     };
261 
262     auto ret = mapSysfsString(chargingPolicy, batteryChargingPolicyMap);
263     if (!ret) {
264         *ret = BatteryChargingPolicy::DEFAULT;
265     }
266 
267     return *ret;
268 }
269 
getBatteryChargingState(const char * chargingState)270 BatteryChargingState getBatteryChargingState(const char* chargingState) {
271     static SysfsStringEnumMap<BatteryChargingState> batteryChargingStateMap[] = {
272             {"0", BatteryChargingState::INVALID},   {"1", BatteryChargingState::NORMAL},
273             {"2", BatteryChargingState::TOO_COLD},  {"3", BatteryChargingState::TOO_HOT},
274             {"4", BatteryChargingState::LONG_LIFE}, {"5", BatteryChargingState::ADAPTIVE},
275             {NULL, BatteryChargingState::NORMAL},
276     };
277 
278     auto ret = mapSysfsString(chargingState, batteryChargingStateMap);
279     if (!ret) {
280         *ret = BatteryChargingState::NORMAL;
281     }
282 
283     return *ret;
284 }
285 
readFromFile(const String8 & path,std::string * buf)286 static int readFromFile(const String8& path, std::string* buf) {
287     buf->clear();
288     if (android::base::ReadFileToString(path.c_str(), buf)) {
289         *buf = android::base::Trim(*buf);
290     }
291     return buf->length();
292 }
293 
writeToFile(const String8 & path,int32_t in_value)294 static bool writeToFile(const String8& path, int32_t in_value) {
295     return android::base::WriteStringToFile(std::to_string(in_value), path.c_str());
296 }
297 
readPowerSupplyType(const String8 & path)298 static BatteryMonitor::PowerSupplyType readPowerSupplyType(const String8& path) {
299     static SysfsStringEnumMap<int> supplyTypeMap[] = {
300             {"Unknown", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN},
301             {"Battery", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_BATTERY},
302             {"UPS", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
303             {"Mains", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
304             {"USB", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_USB},
305             {"USB_DCP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
306             {"USB_HVDCP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
307             {"USB_CDP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
308             {"USB_ACA", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
309             {"USB_C", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
310             {"USB_PD", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
311             {"USB_PD_DRP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_USB},
312             {"Wireless", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_WIRELESS},
313             {"Dock", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_DOCK},
314             {NULL, 0},
315     };
316     std::string buf;
317 
318     if (readFromFile(path, &buf) <= 0) {
319         return BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
320     }
321 
322     auto ret = mapSysfsString(buf.c_str(), supplyTypeMap);
323     if (!ret) {
324         KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
325         *ret = BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
326     }
327 
328     return static_cast<BatteryMonitor::PowerSupplyType>(*ret);
329 }
330 
getBooleanField(const String8 & path)331 static bool getBooleanField(const String8& path) {
332     std::string buf;
333     bool value = false;
334 
335     if (readFromFile(path, &buf) > 0)
336         if (buf[0] != '0')
337             value = true;
338 
339     return value;
340 }
341 
getIntField(const String8 & path)342 static int getIntField(const String8& path) {
343     std::string buf;
344     int value = 0;
345 
346     if (readFromFile(path, &buf) > 0)
347         android::base::ParseInt(buf, &value);
348 
349     return value;
350 }
351 
isScopedPowerSupply(const char * name)352 static bool isScopedPowerSupply(const char* name) {
353     constexpr char kScopeDevice[] = "Device";
354 
355     String8 path;
356     path.appendFormat("%s/%s/scope", POWER_SUPPLY_SYSFS_PATH, name);
357     std::string scope;
358     return (readFromFile(path, &scope) > 0 && scope == kScopeDevice);
359 }
360 
updateValues(void)361 void BatteryMonitor::updateValues(void) {
362     initHealthInfo(mHealthInfo.get());
363 
364     if (!mHealthdConfig->batteryPresentPath.isEmpty())
365         mHealthInfo->batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
366     else
367         mHealthInfo->batteryPresent = mBatteryDevicePresent;
368 
369     mHealthInfo->batteryLevel = mBatteryFixedCapacity
370                                         ? mBatteryFixedCapacity
371                                         : getIntField(mHealthdConfig->batteryCapacityPath);
372     mHealthInfo->batteryVoltageMillivolts = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
373 
374     if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
375         mHealthInfo->batteryCurrentMicroamps = getIntField(mHealthdConfig->batteryCurrentNowPath);
376 
377     if (!mHealthdConfig->batteryFullChargePath.isEmpty())
378         mHealthInfo->batteryFullChargeUah = getIntField(mHealthdConfig->batteryFullChargePath);
379 
380     if (!mHealthdConfig->batteryCycleCountPath.isEmpty())
381         mHealthInfo->batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
382 
383     if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
384         mHealthInfo->batteryChargeCounterUah =
385                 getIntField(mHealthdConfig->batteryChargeCounterPath);
386 
387     if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty())
388         mHealthInfo->batteryCurrentAverageMicroamps =
389                 getIntField(mHealthdConfig->batteryCurrentAvgPath);
390 
391     if (!mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty())
392         mHealthInfo->batteryChargeTimeToFullNowSeconds =
393                 getIntField(mHealthdConfig->batteryChargeTimeToFullNowPath);
394 
395     if (!mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty())
396         mHealthInfo->batteryFullChargeDesignCapacityUah =
397                 getIntField(mHealthdConfig->batteryFullChargeDesignCapacityUahPath);
398 
399     if (!mHealthdConfig->batteryHealthStatusPath.isEmpty())
400         mBatteryHealthStatus = getIntField(mHealthdConfig->batteryHealthStatusPath);
401 
402     if (!mHealthdConfig->batteryStateOfHealthPath.isEmpty())
403         mHealthInfo->batteryHealthData->batteryStateOfHealth =
404                 getIntField(mHealthdConfig->batteryStateOfHealthPath);
405 
406     if (!mHealthdConfig->batteryManufacturingDatePath.isEmpty())
407         mHealthInfo->batteryHealthData->batteryManufacturingDateSeconds =
408                 getIntField(mHealthdConfig->batteryManufacturingDatePath);
409 
410     if (!mHealthdConfig->batteryFirstUsageDatePath.isEmpty())
411         mHealthInfo->batteryHealthData->batteryFirstUsageSeconds =
412                 getIntField(mHealthdConfig->batteryFirstUsageDatePath);
413 
414     mHealthInfo->batteryTemperatureTenthsCelsius =
415             mBatteryFixedTemperature ? mBatteryFixedTemperature
416                                      : getIntField(mHealthdConfig->batteryTemperaturePath);
417 
418     std::string buf;
419 
420     if (readFromFile(mHealthdConfig->batteryCapacityLevelPath, &buf) > 0)
421         mHealthInfo->batteryCapacityLevel = getBatteryCapacityLevel(buf.c_str());
422 
423     if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
424         mHealthInfo->batteryStatus = getBatteryStatus(buf.c_str());
425 
426     // Backward compatible with android.hardware.health V1
427     if (mBatteryHealthStatus < BatteryMonitor::BH_MARGINAL) {
428         if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
429             mHealthInfo->batteryHealth = getBatteryHealth(buf.c_str());
430     } else {
431         mHealthInfo->batteryHealth = getBatteryHealthStatus(mBatteryHealthStatus);
432     }
433 
434     if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
435         mHealthInfo->batteryTechnology = String8(buf.c_str());
436 
437     if (readFromFile(mHealthdConfig->chargingPolicyPath, &buf) > 0)
438         mHealthInfo->chargingPolicy = getBatteryChargingPolicy(buf.c_str());
439 
440     if (readFromFile(mHealthdConfig->chargingStatePath, &buf) > 0)
441         mHealthInfo->chargingState = getBatteryChargingState(buf.c_str());
442 
443     double MaxPower = 0;
444 
445     for (size_t i = 0; i < mChargerNames.size(); i++) {
446         String8 path;
447         path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
448                           mChargerNames[i].string());
449         if (getIntField(path)) {
450             path.clear();
451             path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
452                               mChargerNames[i].string());
453             switch(readPowerSupplyType(path)) {
454             case ANDROID_POWER_SUPPLY_TYPE_AC:
455                 mHealthInfo->chargerAcOnline = true;
456                 break;
457             case ANDROID_POWER_SUPPLY_TYPE_USB:
458                 mHealthInfo->chargerUsbOnline = true;
459                 break;
460             case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
461                 mHealthInfo->chargerWirelessOnline = true;
462                 break;
463             case ANDROID_POWER_SUPPLY_TYPE_DOCK:
464                 mHealthInfo->chargerDockOnline = true;
465                 break;
466             default:
467                 path.clear();
468                 path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH,
469                                   mChargerNames[i].string());
470                 if (access(path.string(), R_OK) == 0)
471                     mHealthInfo->chargerDockOnline = true;
472                 else
473                     KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
474                                  mChargerNames[i].string());
475             }
476             path.clear();
477             path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
478                               mChargerNames[i].string());
479             int ChargingCurrent =
480                     (access(path.string(), R_OK) == 0) ? getIntField(path) : 0;
481 
482             path.clear();
483             path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
484                               mChargerNames[i].string());
485 
486             int ChargingVoltage =
487                 (access(path.string(), R_OK) == 0) ? getIntField(path) :
488                 DEFAULT_VBUS_VOLTAGE;
489 
490             double power = ((double)ChargingCurrent / MILLION) *
491                            ((double)ChargingVoltage / MILLION);
492             if (MaxPower < power) {
493                 mHealthInfo->maxChargingCurrentMicroamps = ChargingCurrent;
494                 mHealthInfo->maxChargingVoltageMicrovolts = ChargingVoltage;
495                 MaxPower = power;
496             }
497         }
498     }
499 }
500 
doLogValues(const HealthInfo & props,const struct healthd_config & healthd_config)501 static void doLogValues(const HealthInfo& props, const struct healthd_config& healthd_config) {
502     char dmesgline[256];
503     size_t len;
504     if (props.batteryPresent) {
505         snprintf(dmesgline, sizeof(dmesgline), "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
506                  props.batteryLevel, props.batteryVoltageMillivolts,
507                  props.batteryTemperatureTenthsCelsius < 0 ? "-" : "",
508                  abs(props.batteryTemperatureTenthsCelsius / 10),
509                  abs(props.batteryTemperatureTenthsCelsius % 10), props.batteryHealth,
510                  props.batteryStatus);
511 
512         len = strlen(dmesgline);
513         if (!healthd_config.batteryCurrentNowPath.isEmpty()) {
514             len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " c=%d",
515                             props.batteryCurrentMicroamps);
516         }
517 
518         if (!healthd_config.batteryFullChargePath.isEmpty()) {
519             len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " fc=%d",
520                             props.batteryFullChargeUah);
521         }
522 
523         if (!healthd_config.batteryCycleCountPath.isEmpty()) {
524             len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " cc=%d",
525                             props.batteryCycleCount);
526         }
527     } else {
528         len = snprintf(dmesgline, sizeof(dmesgline), "battery none");
529     }
530 
531     snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s%s",
532              props.chargerAcOnline ? "a" : "", props.chargerUsbOnline ? "u" : "",
533              props.chargerWirelessOnline ? "w" : "", props.chargerDockOnline ? "d" : "");
534 
535     KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
536 }
537 
logValues(const HealthInfo_2_1 & health_info,const struct healthd_config & healthd_config)538 void BatteryMonitor::logValues(const HealthInfo_2_1& health_info,
539                                const struct healthd_config& healthd_config) {
540     HealthInfo aidl_health_info;
541     (void)android::h2a::translate(health_info, &aidl_health_info);
542     doLogValues(aidl_health_info, healthd_config);
543 }
544 
logValues(void)545 void BatteryMonitor::logValues(void) {
546     doLogValues(*mHealthInfo, *mHealthdConfig);
547 }
548 
isChargerOnline()549 bool BatteryMonitor::isChargerOnline() {
550     const HealthInfo& props = *mHealthInfo;
551     return props.chargerAcOnline | props.chargerUsbOnline | props.chargerWirelessOnline |
552            props.chargerDockOnline;
553 }
554 
getChargeStatus()555 int BatteryMonitor::getChargeStatus() {
556     BatteryStatus result = BatteryStatus::UNKNOWN;
557     if (!mHealthdConfig->batteryStatusPath.isEmpty()) {
558         std::string buf;
559         if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
560             result = getBatteryStatus(buf.c_str());
561     }
562     return static_cast<int>(result);
563 }
564 
setChargingPolicy(int value)565 status_t BatteryMonitor::setChargingPolicy(int value) {
566     status_t ret = NAME_NOT_FOUND;
567     bool result;
568     if (!mHealthdConfig->chargingPolicyPath.isEmpty()) {
569         result = writeToFile(mHealthdConfig->chargingPolicyPath, value);
570         if (!result) {
571             KLOG_WARNING(LOG_TAG, "setChargingPolicy fail\n");
572             ret = BAD_VALUE;
573         } else {
574             ret = OK;
575         }
576     }
577     return ret;
578 }
579 
getChargingPolicy()580 int BatteryMonitor::getChargingPolicy() {
581     BatteryChargingPolicy result = BatteryChargingPolicy::DEFAULT;
582     if (!mHealthdConfig->chargingPolicyPath.isEmpty()) {
583         std::string buf;
584         if (readFromFile(mHealthdConfig->chargingPolicyPath, &buf) > 0)
585             result = getBatteryChargingPolicy(buf.c_str());
586     }
587     return static_cast<int>(result);
588 }
589 
getBatteryHealthData(int id)590 int BatteryMonitor::getBatteryHealthData(int id) {
591     if (id == BATTERY_PROP_MANUFACTURING_DATE) {
592         if (!mHealthdConfig->batteryManufacturingDatePath.isEmpty())
593             return getIntField(mHealthdConfig->batteryManufacturingDatePath);
594     }
595     if (id == BATTERY_PROP_FIRST_USAGE_DATE) {
596         if (!mHealthdConfig->batteryFirstUsageDatePath.isEmpty())
597             return getIntField(mHealthdConfig->batteryFirstUsageDatePath);
598     }
599     if (id == BATTERY_PROP_STATE_OF_HEALTH) {
600         if (!mHealthdConfig->batteryStateOfHealthPath.isEmpty())
601             return getIntField(mHealthdConfig->batteryStateOfHealthPath);
602     }
603     return 0;
604 }
605 
getProperty(int id,struct BatteryProperty * val)606 status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
607     status_t ret = BAD_VALUE;
608     std::string buf;
609 
610     val->valueInt64 = LONG_MIN;
611 
612     switch(id) {
613     case BATTERY_PROP_CHARGE_COUNTER:
614         if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
615             val->valueInt64 =
616                 getIntField(mHealthdConfig->batteryChargeCounterPath);
617             ret = OK;
618         } else {
619             ret = NAME_NOT_FOUND;
620         }
621         break;
622 
623     case BATTERY_PROP_CURRENT_NOW:
624         if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
625             val->valueInt64 =
626                 getIntField(mHealthdConfig->batteryCurrentNowPath);
627             ret = OK;
628         } else {
629             ret = NAME_NOT_FOUND;
630         }
631         break;
632 
633     case BATTERY_PROP_CURRENT_AVG:
634         if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
635             val->valueInt64 =
636                 getIntField(mHealthdConfig->batteryCurrentAvgPath);
637             ret = OK;
638         } else {
639             ret = NAME_NOT_FOUND;
640         }
641         break;
642 
643     case BATTERY_PROP_CAPACITY:
644         if (!mHealthdConfig->batteryCapacityPath.isEmpty()) {
645             val->valueInt64 =
646                 getIntField(mHealthdConfig->batteryCapacityPath);
647             ret = OK;
648         } else {
649             ret = NAME_NOT_FOUND;
650         }
651         break;
652 
653     case BATTERY_PROP_ENERGY_COUNTER:
654         if (mHealthdConfig->energyCounter) {
655             ret = mHealthdConfig->energyCounter(&val->valueInt64);
656         } else {
657             ret = NAME_NOT_FOUND;
658         }
659         break;
660 
661     case BATTERY_PROP_BATTERY_STATUS:
662         val->valueInt64 = getChargeStatus();
663         ret = OK;
664         break;
665 
666     case BATTERY_PROP_CHARGING_POLICY:
667         val->valueInt64 = getChargingPolicy();
668         ret = OK;
669         break;
670 
671     case BATTERY_PROP_MANUFACTURING_DATE:
672         val->valueInt64 = getBatteryHealthData(BATTERY_PROP_MANUFACTURING_DATE);
673         ret = OK;
674         break;
675 
676     case BATTERY_PROP_FIRST_USAGE_DATE:
677         val->valueInt64 = getBatteryHealthData(BATTERY_PROP_FIRST_USAGE_DATE);
678         ret = OK;
679         break;
680 
681     case BATTERY_PROP_STATE_OF_HEALTH:
682         val->valueInt64 = getBatteryHealthData(BATTERY_PROP_STATE_OF_HEALTH);
683         ret = OK;
684         break;
685 
686     default:
687         break;
688     }
689 
690     return ret;
691 }
692 
dumpState(int fd)693 void BatteryMonitor::dumpState(int fd) {
694     int v;
695     char vs[128];
696     const HealthInfo& props = *mHealthInfo;
697 
698     snprintf(vs, sizeof(vs),
699              "ac: %d usb: %d wireless: %d dock: %d current_max: %d voltage_max: %d\n",
700              props.chargerAcOnline, props.chargerUsbOnline, props.chargerWirelessOnline,
701              props.chargerDockOnline, props.maxChargingCurrentMicroamps,
702              props.maxChargingVoltageMicrovolts);
703     write(fd, vs, strlen(vs));
704     snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
705              props.batteryStatus, props.batteryHealth, props.batteryPresent);
706     write(fd, vs, strlen(vs));
707     snprintf(vs, sizeof(vs), "level: %d voltage: %d temp: %d\n", props.batteryLevel,
708              props.batteryVoltageMillivolts, props.batteryTemperatureTenthsCelsius);
709     write(fd, vs, strlen(vs));
710 
711     if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
712         v = getIntField(mHealthdConfig->batteryCurrentNowPath);
713         snprintf(vs, sizeof(vs), "current now: %d\n", v);
714         write(fd, vs, strlen(vs));
715     }
716 
717     if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
718         v = getIntField(mHealthdConfig->batteryCurrentAvgPath);
719         snprintf(vs, sizeof(vs), "current avg: %d\n", v);
720         write(fd, vs, strlen(vs));
721     }
722 
723     if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
724         v = getIntField(mHealthdConfig->batteryChargeCounterPath);
725         snprintf(vs, sizeof(vs), "charge counter: %d\n", v);
726         write(fd, vs, strlen(vs));
727     }
728 
729     if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
730         snprintf(vs, sizeof(vs), "current now: %d\n", props.batteryCurrentMicroamps);
731         write(fd, vs, strlen(vs));
732     }
733 
734     if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
735         snprintf(vs, sizeof(vs), "cycle count: %d\n", props.batteryCycleCount);
736         write(fd, vs, strlen(vs));
737     }
738 
739     if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
740         snprintf(vs, sizeof(vs), "Full charge: %d\n", props.batteryFullChargeUah);
741         write(fd, vs, strlen(vs));
742     }
743 }
744 
init(struct healthd_config * hc)745 void BatteryMonitor::init(struct healthd_config *hc) {
746     String8 path;
747     char pval[PROPERTY_VALUE_MAX];
748 
749     mHealthdConfig = hc;
750     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir);
751     if (dir == NULL) {
752         KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
753     } else {
754         struct dirent* entry;
755 
756         while ((entry = readdir(dir.get()))) {
757             const char* name = entry->d_name;
758 
759             if (!strcmp(name, ".") || !strcmp(name, ".."))
760                 continue;
761 
762             std::vector<String8>::iterator itIgnoreName =
763                     find(hc->ignorePowerSupplyNames.begin(), hc->ignorePowerSupplyNames.end(),
764                          String8(name));
765             if (itIgnoreName != hc->ignorePowerSupplyNames.end())
766                 continue;
767 
768             // Look for "type" file in each subdirectory
769             path.clear();
770             path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
771             switch(readPowerSupplyType(path)) {
772             case ANDROID_POWER_SUPPLY_TYPE_AC:
773             case ANDROID_POWER_SUPPLY_TYPE_USB:
774             case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
775             case ANDROID_POWER_SUPPLY_TYPE_DOCK:
776                 path.clear();
777                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
778                 if (access(path.string(), R_OK) == 0)
779                     mChargerNames.add(String8(name));
780                 break;
781 
782             case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
783                 // Some devices expose the battery status of sub-component like
784                 // stylus. Such a device-scoped battery info needs to be skipped
785                 // in BatteryMonitor, which is intended to report the status of
786                 // the battery supplying the power to the whole system.
787                 if (isScopedPowerSupply(name)) continue;
788                 mBatteryDevicePresent = true;
789 
790                 if (mHealthdConfig->batteryStatusPath.isEmpty()) {
791                     path.clear();
792                     path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
793                                       name);
794                     if (access(path, R_OK) == 0)
795                         mHealthdConfig->batteryStatusPath = path;
796                 }
797 
798                 if (mHealthdConfig->batteryHealthPath.isEmpty()) {
799                     path.clear();
800                     path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
801                                       name);
802                     if (access(path, R_OK) == 0)
803                         mHealthdConfig->batteryHealthPath = path;
804                 }
805 
806                 if (mHealthdConfig->batteryPresentPath.isEmpty()) {
807                     path.clear();
808                     path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
809                                       name);
810                     if (access(path, R_OK) == 0)
811                         mHealthdConfig->batteryPresentPath = path;
812                 }
813 
814                 if (mHealthdConfig->batteryCapacityPath.isEmpty()) {
815                     path.clear();
816                     path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
817                                       name);
818                     if (access(path, R_OK) == 0)
819                         mHealthdConfig->batteryCapacityPath = path;
820                 }
821 
822                 if (mHealthdConfig->batteryVoltagePath.isEmpty()) {
823                     path.clear();
824                     path.appendFormat("%s/%s/voltage_now",
825                                       POWER_SUPPLY_SYSFS_PATH, name);
826                     if (access(path, R_OK) == 0) {
827                         mHealthdConfig->batteryVoltagePath = path;
828                     }
829                 }
830 
831                 if (mHealthdConfig->batteryFullChargePath.isEmpty()) {
832                     path.clear();
833                     path.appendFormat("%s/%s/charge_full",
834                                       POWER_SUPPLY_SYSFS_PATH, name);
835                     if (access(path, R_OK) == 0)
836                         mHealthdConfig->batteryFullChargePath = path;
837                 }
838 
839                 if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
840                     path.clear();
841                     path.appendFormat("%s/%s/current_now",
842                                       POWER_SUPPLY_SYSFS_PATH, name);
843                     if (access(path, R_OK) == 0)
844                         mHealthdConfig->batteryCurrentNowPath = path;
845                 }
846 
847                 if (mHealthdConfig->batteryCycleCountPath.isEmpty()) {
848                     path.clear();
849                     path.appendFormat("%s/%s/cycle_count",
850                                       POWER_SUPPLY_SYSFS_PATH, name);
851                     if (access(path, R_OK) == 0)
852                         mHealthdConfig->batteryCycleCountPath = path;
853                 }
854 
855                 if (mHealthdConfig->batteryCapacityLevelPath.isEmpty()) {
856                     path.clear();
857                     path.appendFormat("%s/%s/capacity_level", POWER_SUPPLY_SYSFS_PATH, name);
858                     if (access(path, R_OK) == 0) mHealthdConfig->batteryCapacityLevelPath = path;
859                 }
860 
861                 if (mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty()) {
862                     path.clear();
863                     path.appendFormat("%s/%s/time_to_full_now", POWER_SUPPLY_SYSFS_PATH, name);
864                     if (access(path, R_OK) == 0)
865                         mHealthdConfig->batteryChargeTimeToFullNowPath = path;
866                 }
867 
868                 if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty()) {
869                     path.clear();
870                     path.appendFormat("%s/%s/charge_full_design", POWER_SUPPLY_SYSFS_PATH, name);
871                     if (access(path, R_OK) == 0)
872                         mHealthdConfig->batteryFullChargeDesignCapacityUahPath = path;
873                 }
874 
875                 if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
876                     path.clear();
877                     path.appendFormat("%s/%s/current_avg",
878                                       POWER_SUPPLY_SYSFS_PATH, name);
879                     if (access(path, R_OK) == 0)
880                         mHealthdConfig->batteryCurrentAvgPath = path;
881                 }
882 
883                 if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
884                     path.clear();
885                     path.appendFormat("%s/%s/charge_counter",
886                                       POWER_SUPPLY_SYSFS_PATH, name);
887                     if (access(path, R_OK) == 0)
888                         mHealthdConfig->batteryChargeCounterPath = path;
889                 }
890 
891                 if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
892                     path.clear();
893                     path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
894                                       name);
895                     if (access(path, R_OK) == 0) {
896                         mHealthdConfig->batteryTemperaturePath = path;
897                     }
898                 }
899 
900                 if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {
901                     path.clear();
902                     path.appendFormat("%s/%s/technology",
903                                       POWER_SUPPLY_SYSFS_PATH, name);
904                     if (access(path, R_OK) == 0)
905                         mHealthdConfig->batteryTechnologyPath = path;
906                 }
907 
908                 if (mHealthdConfig->batteryStateOfHealthPath.isEmpty()) {
909                     path.clear();
910                     path.appendFormat("%s/%s/state_of_health", POWER_SUPPLY_SYSFS_PATH, name);
911                     if (access(path, R_OK) == 0) {
912                         mHealthdConfig->batteryStateOfHealthPath = path;
913                     } else {
914                         path.clear();
915                         path.appendFormat("%s/%s/health_index", POWER_SUPPLY_SYSFS_PATH, name);
916                         if (access(path, R_OK) == 0)
917                             mHealthdConfig->batteryStateOfHealthPath = path;
918                     }
919                 }
920 
921                 if (mHealthdConfig->batteryHealthStatusPath.isEmpty()) {
922                     path.clear();
923                     path.appendFormat("%s/%s/health_status", POWER_SUPPLY_SYSFS_PATH, name);
924                     if (access(path, R_OK) == 0) mHealthdConfig->batteryHealthStatusPath = path;
925                 }
926 
927                 if (mHealthdConfig->batteryManufacturingDatePath.isEmpty()) {
928                     path.clear();
929                     path.appendFormat("%s/%s/manufacturing_date", POWER_SUPPLY_SYSFS_PATH, name);
930                     if (access(path, R_OK) == 0)
931                         mHealthdConfig->batteryManufacturingDatePath = path;
932                 }
933 
934                 if (mHealthdConfig->batteryFirstUsageDatePath.isEmpty()) {
935                     path.clear();
936                     path.appendFormat("%s/%s/first_usage_date", POWER_SUPPLY_SYSFS_PATH, name);
937                     if (access(path, R_OK) == 0) mHealthdConfig->batteryFirstUsageDatePath = path;
938                 }
939 
940                 if (mHealthdConfig->chargingStatePath.isEmpty()) {
941                     path.clear();
942                     path.appendFormat("%s/%s/charging_state", POWER_SUPPLY_SYSFS_PATH, name);
943                     if (access(path, R_OK) == 0) mHealthdConfig->chargingStatePath = path;
944                 }
945 
946                 if (mHealthdConfig->chargingPolicyPath.isEmpty()) {
947                     path.clear();
948                     path.appendFormat("%s/%s/charging_policy", POWER_SUPPLY_SYSFS_PATH, name);
949                     if (access(path, R_OK) == 0) mHealthdConfig->chargingPolicyPath = path;
950                 }
951 
952                 break;
953 
954             case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
955                 break;
956             }
957 
958             // Look for "is_dock" file
959             path.clear();
960             path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH, name);
961             if (access(path.string(), R_OK) == 0) {
962                 path.clear();
963                 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
964                 if (access(path.string(), R_OK) == 0)
965                     mChargerNames.add(String8(name));
966 
967             }
968         }
969     }
970 
971     // Typically the case for devices which do not have a battery and
972     // and are always plugged into AC mains.
973     if (!mBatteryDevicePresent) {
974         KLOG_WARNING(LOG_TAG, "No battery devices found\n");
975         hc->periodic_chores_interval_fast = -1;
976         hc->periodic_chores_interval_slow = -1;
977     } else {
978         if (mHealthdConfig->batteryStatusPath.isEmpty())
979             KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
980         if (mHealthdConfig->batteryHealthPath.isEmpty())
981             KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");
982         if (mHealthdConfig->batteryPresentPath.isEmpty())
983             KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
984         if (mHealthdConfig->batteryCapacityPath.isEmpty())
985             KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
986         if (mHealthdConfig->batteryVoltagePath.isEmpty())
987             KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
988         if (mHealthdConfig->batteryTemperaturePath.isEmpty())
989             KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
990         if (mHealthdConfig->batteryTechnologyPath.isEmpty())
991             KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
992         if (mHealthdConfig->batteryCurrentNowPath.isEmpty())
993             KLOG_WARNING(LOG_TAG, "BatteryCurrentNowPath not found\n");
994         if (mHealthdConfig->batteryFullChargePath.isEmpty())
995             KLOG_WARNING(LOG_TAG, "BatteryFullChargePath not found\n");
996         if (mHealthdConfig->batteryCycleCountPath.isEmpty())
997             KLOG_WARNING(LOG_TAG, "BatteryCycleCountPath not found\n");
998         if (mHealthdConfig->batteryCapacityLevelPath.isEmpty())
999             KLOG_WARNING(LOG_TAG, "batteryCapacityLevelPath not found\n");
1000         if (mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty())
1001             KLOG_WARNING(LOG_TAG, "batteryChargeTimeToFullNowPath. not found\n");
1002         if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty())
1003             KLOG_WARNING(LOG_TAG, "batteryFullChargeDesignCapacityUahPath. not found\n");
1004         if (mHealthdConfig->batteryStateOfHealthPath.isEmpty())
1005             KLOG_WARNING(LOG_TAG, "batteryStateOfHealthPath not found\n");
1006         if (mHealthdConfig->batteryHealthStatusPath.isEmpty())
1007             KLOG_WARNING(LOG_TAG, "batteryHealthStatusPath not found\n");
1008         if (mHealthdConfig->batteryManufacturingDatePath.isEmpty())
1009             KLOG_WARNING(LOG_TAG, "batteryManufacturingDatePath not found\n");
1010         if (mHealthdConfig->batteryFirstUsageDatePath.isEmpty())
1011             KLOG_WARNING(LOG_TAG, "batteryFirstUsageDatePath not found\n");
1012         if (mHealthdConfig->chargingStatePath.isEmpty())
1013             KLOG_WARNING(LOG_TAG, "chargingStatePath not found\n");
1014         if (mHealthdConfig->chargingPolicyPath.isEmpty())
1015             KLOG_WARNING(LOG_TAG, "chargingPolicyPath not found\n");
1016     }
1017 
1018     if (property_get("ro.boot.fake_battery", pval, NULL) > 0
1019                                                && strtol(pval, NULL, 10) != 0) {
1020         mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;
1021         mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
1022     }
1023 }
1024 
1025 }; // namespace android
1026