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