blob: 45882a687a2292a16e98684356436e5ae3b76733 [file] [log] [blame]
Todd Poynor752faf22013-06-12 13:25:59 -07001/*
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
Yabin Cuie98e1772016-02-17 12:21:34 -080019#include <healthd/healthd.h>
20#include <healthd/BatteryMonitor.h>
Todd Poynor752faf22013-06-12 13:25:59 -070021
22#include <dirent.h>
23#include <errno.h>
24#include <fcntl.h>
25#include <stdio.h>
26#include <stdlib.h>
Mark Salyzynacb1ddf2015-07-23 09:22:50 -070027#include <sys/types.h>
Todd Poynor752faf22013-06-12 13:25:59 -070028#include <unistd.h>
Thierry Strudelf73de6f2019-01-11 17:09:20 -080029
30#include <algorithm>
James Hawkins588a2ca2016-02-18 14:52:46 -080031#include <memory>
Yifan Hong1d4368b2019-10-07 11:18:04 -070032#include <optional>
Mark Salyzynacb1ddf2015-07-23 09:22:50 -070033
Yifan Hongb99d15c2022-03-01 12:12:34 -080034#include <aidl/android/hardware/health/HealthInfo.h>
Michael Scott3217c5c2016-06-05 11:20:13 -070035#include <android-base/file.h>
Elliott Hughesda46b392016-10-11 17:09:00 -070036#include <android-base/parseint.h>
Michael Scott3217c5c2016-06-05 11:20:13 -070037#include <android-base/strings.h>
Yifan Hong1d4368b2019-10-07 11:18:04 -070038#include <android/hardware/health/2.1/types.h>
Yifan Hongb99d15c2022-03-01 12:12:34 -080039#include <android/hardware/health/translate-ndk.h>
Todd Poynor752faf22013-06-12 13:25:59 -070040#include <batteryservice/BatteryService.h>
41#include <cutils/klog.h>
Todd Poynor3db03a52014-05-21 16:28:13 -070042#include <cutils/properties.h>
Todd Poynorc133b712013-08-14 17:39:13 -070043#include <utils/Errors.h>
Todd Poynor752faf22013-06-12 13:25:59 -070044#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
Ruchi Kandoia78fc232014-07-10 15:06:21 -070049#define FAKE_BATTERY_CAPACITY 42
50#define FAKE_BATTERY_TEMPERATURE 424
Ruchi Kandoi5c09ec12016-02-25 16:19:30 -080051#define MILLION 1.0e6
Badhri Jagan Sridharan40e1df42015-10-27 10:43:53 -070052#define DEFAULT_VBUS_VOLTAGE 5000000
Todd Poynor752faf22013-06-12 13:25:59 -070053
Yifan Hong1d4368b2019-10-07 11:18:04 -070054using HealthInfo_1_0 = android::hardware::health::V1_0::HealthInfo;
55using HealthInfo_2_0 = android::hardware::health::V2_0::HealthInfo;
56using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
Yifan Hongb99d15c2022-03-01 12:12:34 -080057using aidl::android::hardware::health::BatteryCapacityLevel;
58using aidl::android::hardware::health::BatteryHealth;
59using aidl::android::hardware::health::BatteryStatus;
60using aidl::android::hardware::health::HealthInfo;
61
62namespace {
63
64// Translate from AIDL back to HIDL definition for getHealthInfo_*_* calls.
65// Skips storageInfo and diskStats.
66void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
67 ::android::hardware::health::V1_0::HealthInfo* out) {
68 out->chargerAcOnline = in.chargerAcOnline;
69 out->chargerUsbOnline = in.chargerUsbOnline;
70 out->chargerWirelessOnline = in.chargerWirelessOnline;
71 out->maxChargingCurrent = in.maxChargingCurrentMicroamps;
72 out->maxChargingVoltage = in.maxChargingVoltageMicrovolts;
73 out->batteryStatus =
74 static_cast<::android::hardware::health::V1_0::BatteryStatus>(in.batteryStatus);
75 out->batteryHealth =
76 static_cast<::android::hardware::health::V1_0::BatteryHealth>(in.batteryHealth);
77 out->batteryPresent = in.batteryPresent;
78 out->batteryLevel = in.batteryLevel;
79 out->batteryVoltage = in.batteryVoltageMillivolts;
80 out->batteryTemperature = in.batteryTemperatureTenthsCelsius;
81 out->batteryCurrent = in.batteryCurrentMicroamps;
82 out->batteryCycleCount = in.batteryCycleCount;
83 out->batteryFullCharge = in.batteryFullChargeUah;
84 out->batteryChargeCounter = in.batteryChargeCounterUah;
85 out->batteryTechnology = in.batteryTechnology;
86}
87
88void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
89 ::android::hardware::health::V2_0::HealthInfo* out) {
90 translateToHidl(in, &out->legacy);
91 out->batteryCurrentAverage = in.batteryCurrentAverageMicroamps;
92 // Skip storageInfo and diskStats
93}
94
95void translateToHidl(const ::aidl::android::hardware::health::HealthInfo& in,
96 ::android::hardware::health::V2_1::HealthInfo* out) {
97 translateToHidl(in, &out->legacy);
98 out->batteryCapacityLevel = static_cast<android::hardware::health::V2_1::BatteryCapacityLevel>(
99 in.batteryCapacityLevel);
100 out->batteryChargeTimeToFullNowSeconds = in.batteryChargeTimeToFullNowSeconds;
101 out->batteryFullChargeDesignCapacityUah = in.batteryFullChargeDesignCapacityUah;
102}
103
104} // namespace
Yifan Hong1d4368b2019-10-07 11:18:04 -0700105
Todd Poynor752faf22013-06-12 13:25:59 -0700106namespace android {
107
Yifan Hong1d4368b2019-10-07 11:18:04 -0700108template <typename T>
109struct SysfsStringEnumMap {
Mark Salyzyn6f5b47f2014-05-15 15:00:59 -0700110 const char* s;
Yifan Hong1d4368b2019-10-07 11:18:04 -0700111 T val;
Todd Poynor752faf22013-06-12 13:25:59 -0700112};
113
Yifan Hong1d4368b2019-10-07 11:18:04 -0700114template <typename T>
115static std::optional<T> mapSysfsString(const char* str, SysfsStringEnumMap<T> map[]) {
Todd Poynor752faf22013-06-12 13:25:59 -0700116 for (int i = 0; map[i].s; i++)
117 if (!strcmp(str, map[i].s))
118 return map[i].val;
119
Yifan Hong1d4368b2019-10-07 11:18:04 -0700120 return std::nullopt;
Yabin Cuidb04a492016-02-16 17:19:23 -0800121}
122
Yifan Hongb99d15c2022-03-01 12:12:34 -0800123static void initHealthInfo(HealthInfo* health_info) {
Bart Van Assche024e18f2022-02-24 21:22:07 +0000124 *health_info = {
125 .batteryCapacityLevel = BatteryCapacityLevel::UNSUPPORTED,
126 .batteryChargeTimeToFullNowSeconds =
127 (int64_t)HealthInfo::BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED,
128 .batteryStatus = BatteryStatus::UNKNOWN,
129 .batteryHealth = BatteryHealth::UNKNOWN,
130 };
Yifan Hong6cabe9b2019-11-05 17:04:50 -0800131}
132
Todd Poynore030a102018-01-19 14:03:59 -0800133BatteryMonitor::BatteryMonitor()
134 : mHealthdConfig(nullptr),
135 mBatteryDevicePresent(false),
136 mBatteryFixedCapacity(0),
Yifan Hong1d4368b2019-10-07 11:18:04 -0700137 mBatteryFixedTemperature(0),
Yifan Hongb99d15c2022-03-01 12:12:34 -0800138 mHealthInfo(std::make_unique<HealthInfo>()) {
Yifan Hong6cabe9b2019-11-05 17:04:50 -0800139 initHealthInfo(mHealthInfo.get());
140}
Yifan Hong1d4368b2019-10-07 11:18:04 -0700141
142BatteryMonitor::~BatteryMonitor() {}
143
Yifan Hongb99d15c2022-03-01 12:12:34 -0800144HealthInfo_1_0 BatteryMonitor::getHealthInfo_1_0() const {
145 HealthInfo_1_0 health_info_1_0;
146 translateToHidl(*mHealthInfo, &health_info_1_0);
147 return health_info_1_0;
Yabin Cuidb04a492016-02-16 17:19:23 -0800148}
149
Yifan Hongb99d15c2022-03-01 12:12:34 -0800150HealthInfo_2_0 BatteryMonitor::getHealthInfo_2_0() const {
151 HealthInfo_2_0 health_info_2_0;
152 translateToHidl(*mHealthInfo, &health_info_2_0);
153 return health_info_2_0;
Hridya Valsaraju7fa72252018-01-12 17:44:33 -0800154}
155
Yifan Hongb99d15c2022-03-01 12:12:34 -0800156HealthInfo_2_1 BatteryMonitor::getHealthInfo_2_1() const {
157 HealthInfo_2_1 health_info_2_1;
158 translateToHidl(*mHealthInfo, &health_info_2_1);
159 return health_info_2_1;
160}
161
162const HealthInfo& BatteryMonitor::getHealthInfo() const {
Yifan Hong1d4368b2019-10-07 11:18:04 -0700163 return *mHealthInfo;
164}
165
166BatteryStatus getBatteryStatus(const char* status) {
167 static SysfsStringEnumMap<BatteryStatus> batteryStatusMap[] = {
168 {"Unknown", BatteryStatus::UNKNOWN},
169 {"Charging", BatteryStatus::CHARGING},
170 {"Discharging", BatteryStatus::DISCHARGING},
171 {"Not charging", BatteryStatus::NOT_CHARGING},
172 {"Full", BatteryStatus::FULL},
173 {NULL, BatteryStatus::UNKNOWN},
Todd Poynor752faf22013-06-12 13:25:59 -0700174 };
175
Yifan Hong1d4368b2019-10-07 11:18:04 -0700176 auto ret = mapSysfsString(status, batteryStatusMap);
177 if (!ret) {
Todd Poynor752faf22013-06-12 13:25:59 -0700178 KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
Yifan Hong1d4368b2019-10-07 11:18:04 -0700179 *ret = BatteryStatus::UNKNOWN;
Todd Poynor752faf22013-06-12 13:25:59 -0700180 }
181
Yifan Hong1d4368b2019-10-07 11:18:04 -0700182 return *ret;
Todd Poynor752faf22013-06-12 13:25:59 -0700183}
184
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800185BatteryCapacityLevel getBatteryCapacityLevel(const char* capacityLevel) {
186 static SysfsStringEnumMap<BatteryCapacityLevel> batteryCapacityLevelMap[] = {
187 {"Unknown", BatteryCapacityLevel::UNKNOWN},
188 {"Critical", BatteryCapacityLevel::CRITICAL},
189 {"Low", BatteryCapacityLevel::LOW},
190 {"Normal", BatteryCapacityLevel::NORMAL},
191 {"High", BatteryCapacityLevel::HIGH},
192 {"Full", BatteryCapacityLevel::FULL},
Stephane Lee06846042020-02-12 17:00:24 -0800193 {NULL, BatteryCapacityLevel::UNSUPPORTED},
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800194 };
195
196 auto ret = mapSysfsString(capacityLevel, batteryCapacityLevelMap);
197 if (!ret) {
Stephane Lee06846042020-02-12 17:00:24 -0800198 KLOG_WARNING(LOG_TAG, "Unsupported battery capacity level '%s'\n", capacityLevel);
199 *ret = BatteryCapacityLevel::UNSUPPORTED;
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800200 }
201
202 return *ret;
203}
204
Yifan Hong1d4368b2019-10-07 11:18:04 -0700205BatteryHealth getBatteryHealth(const char* status) {
206 static SysfsStringEnumMap<BatteryHealth> batteryHealthMap[] = {
207 {"Unknown", BatteryHealth::UNKNOWN},
208 {"Good", BatteryHealth::GOOD},
209 {"Overheat", BatteryHealth::OVERHEAT},
210 {"Dead", BatteryHealth::DEAD},
211 {"Over voltage", BatteryHealth::OVER_VOLTAGE},
212 {"Unspecified failure", BatteryHealth::UNSPECIFIED_FAILURE},
213 {"Cold", BatteryHealth::COLD},
214 // battery health values from JEITA spec
215 {"Warm", BatteryHealth::GOOD},
216 {"Cool", BatteryHealth::GOOD},
217 {"Hot", BatteryHealth::OVERHEAT},
218 {NULL, BatteryHealth::UNKNOWN},
Todd Poynor752faf22013-06-12 13:25:59 -0700219 };
220
Yifan Hong1d4368b2019-10-07 11:18:04 -0700221 auto ret = mapSysfsString(status, batteryHealthMap);
222 if (!ret) {
Todd Poynor752faf22013-06-12 13:25:59 -0700223 KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
Yifan Hong1d4368b2019-10-07 11:18:04 -0700224 *ret = BatteryHealth::UNKNOWN;
Todd Poynor752faf22013-06-12 13:25:59 -0700225 }
226
Yifan Hong1d4368b2019-10-07 11:18:04 -0700227 return *ret;
Todd Poynor752faf22013-06-12 13:25:59 -0700228}
229
Michael Scott3217c5c2016-06-05 11:20:13 -0700230int BatteryMonitor::readFromFile(const String8& path, std::string* buf) {
Steven Moreland2aac3352017-03-10 22:31:08 -0800231 if (android::base::ReadFileToString(path.c_str(), buf)) {
Michael Scott3217c5c2016-06-05 11:20:13 -0700232 *buf = android::base::Trim(*buf);
Todd Poynor752faf22013-06-12 13:25:59 -0700233 }
Michael Scott3217c5c2016-06-05 11:20:13 -0700234 return buf->length();
Todd Poynor752faf22013-06-12 13:25:59 -0700235}
236
237BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
Yifan Hong1d4368b2019-10-07 11:18:04 -0700238 static SysfsStringEnumMap<int> supplyTypeMap[] = {
239 {"Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN},
240 {"Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY},
241 {"UPS", ANDROID_POWER_SUPPLY_TYPE_AC},
242 {"Mains", ANDROID_POWER_SUPPLY_TYPE_AC},
243 {"USB", ANDROID_POWER_SUPPLY_TYPE_USB},
244 {"USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC},
245 {"USB_HVDCP", ANDROID_POWER_SUPPLY_TYPE_AC},
246 {"USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC},
247 {"USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC},
248 {"USB_C", ANDROID_POWER_SUPPLY_TYPE_AC},
249 {"USB_PD", ANDROID_POWER_SUPPLY_TYPE_AC},
250 {"USB_PD_DRP", ANDROID_POWER_SUPPLY_TYPE_USB},
251 {"Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS},
Jack Wu06b90412021-12-15 20:40:21 +0800252 {"Dock", ANDROID_POWER_SUPPLY_TYPE_DOCK},
Yifan Hong1d4368b2019-10-07 11:18:04 -0700253 {NULL, 0},
Todd Poynor752faf22013-06-12 13:25:59 -0700254 };
Yifan Hong1d4368b2019-10-07 11:18:04 -0700255 std::string buf;
Todd Poynor752faf22013-06-12 13:25:59 -0700256
Michael Scott3217c5c2016-06-05 11:20:13 -0700257 if (readFromFile(path, &buf) <= 0)
Todd Poynor752faf22013-06-12 13:25:59 -0700258 return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
259
Yifan Hong1d4368b2019-10-07 11:18:04 -0700260 auto ret = mapSysfsString(buf.c_str(), supplyTypeMap);
John Stultz47a6bf02019-11-06 00:23:34 +0000261 if (!ret) {
Michael Scott3217c5c2016-06-05 11:20:13 -0700262 KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
Yifan Hong1d4368b2019-10-07 11:18:04 -0700263 *ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
Johan Redestig32828612016-02-03 13:45:54 +0100264 }
Todd Poynor752faf22013-06-12 13:25:59 -0700265
Yifan Hong1d4368b2019-10-07 11:18:04 -0700266 return static_cast<BatteryMonitor::PowerSupplyType>(*ret);
Todd Poynor752faf22013-06-12 13:25:59 -0700267}
268
269bool BatteryMonitor::getBooleanField(const String8& path) {
Michael Scott3217c5c2016-06-05 11:20:13 -0700270 std::string buf;
Todd Poynor752faf22013-06-12 13:25:59 -0700271 bool value = false;
Michael Scott3217c5c2016-06-05 11:20:13 -0700272
273 if (readFromFile(path, &buf) > 0)
274 if (buf[0] != '0')
Todd Poynor752faf22013-06-12 13:25:59 -0700275 value = true;
Todd Poynor752faf22013-06-12 13:25:59 -0700276
277 return value;
278}
279
280int BatteryMonitor::getIntField(const String8& path) {
Michael Scott3217c5c2016-06-05 11:20:13 -0700281 std::string buf;
Todd Poynor752faf22013-06-12 13:25:59 -0700282 int value = 0;
Michael Scott3217c5c2016-06-05 11:20:13 -0700283
284 if (readFromFile(path, &buf) > 0)
Elliott Hughesda46b392016-10-11 17:09:00 -0700285 android::base::ParseInt(buf, &value);
Michael Scott3217c5c2016-06-05 11:20:13 -0700286
Todd Poynor752faf22013-06-12 13:25:59 -0700287 return value;
288}
289
Kazuhiro Inaba8e4d9822019-06-12 13:46:08 +0900290bool BatteryMonitor::isScopedPowerSupply(const char* name) {
291 constexpr char kScopeDevice[] = "Device";
292
293 String8 path;
294 path.appendFormat("%s/%s/scope", POWER_SUPPLY_SYSFS_PATH, name);
295 std::string scope;
296 return (readFromFile(path, &scope) > 0 && scope == kScopeDevice);
297}
298
Yifan Hong1353e702019-10-07 10:41:30 -0700299void BatteryMonitor::updateValues(void) {
Yifan Hong6cabe9b2019-11-05 17:04:50 -0800300 initHealthInfo(mHealthInfo.get());
Yifan Hong1d4368b2019-10-07 11:18:04 -0700301
Todd Poynorf5d30122013-08-12 17:03:35 -0700302 if (!mHealthdConfig->batteryPresentPath.isEmpty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800303 mHealthInfo->batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
Todd Poynor752faf22013-06-12 13:25:59 -0700304 else
Yifan Hongb99d15c2022-03-01 12:12:34 -0800305 mHealthInfo->batteryPresent = mBatteryDevicePresent;
Todd Poynor752faf22013-06-12 13:25:59 -0700306
Yifan Hongb99d15c2022-03-01 12:12:34 -0800307 mHealthInfo->batteryLevel = mBatteryFixedCapacity
308 ? mBatteryFixedCapacity
309 : getIntField(mHealthdConfig->batteryCapacityPath);
310 mHealthInfo->batteryVoltageMillivolts = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
Todd Poynorb45f1f52013-07-30 18:57:16 -0700311
Ruchi Kandoicc338802015-08-24 13:01:16 -0700312 if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800313 mHealthInfo->batteryCurrentMicroamps = getIntField(mHealthdConfig->batteryCurrentNowPath);
Ruchi Kandoicc338802015-08-24 13:01:16 -0700314
315 if (!mHealthdConfig->batteryFullChargePath.isEmpty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800316 mHealthInfo->batteryFullChargeUah = getIntField(mHealthdConfig->batteryFullChargePath);
Ruchi Kandoicc338802015-08-24 13:01:16 -0700317
318 if (!mHealthdConfig->batteryCycleCountPath.isEmpty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800319 mHealthInfo->batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
Ruchi Kandoicc338802015-08-24 13:01:16 -0700320
Ruchi Kandoi3f9886b2016-04-07 12:34:40 -0700321 if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800322 mHealthInfo->batteryChargeCounterUah =
323 getIntField(mHealthdConfig->batteryChargeCounterPath);
Ruchi Kandoi3f9886b2016-04-07 12:34:40 -0700324
Yifan Hong35cb0832019-10-07 13:58:29 -0700325 if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800326 mHealthInfo->batteryCurrentAverageMicroamps =
Yifan Hong35cb0832019-10-07 13:58:29 -0700327 getIntField(mHealthdConfig->batteryCurrentAvgPath);
328
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800329 if (!mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty())
330 mHealthInfo->batteryChargeTimeToFullNowSeconds =
331 getIntField(mHealthdConfig->batteryChargeTimeToFullNowPath);
332
Stephane Lee1c108ed2020-02-10 18:23:57 -0800333 if (!mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty())
334 mHealthInfo->batteryFullChargeDesignCapacityUah =
335 getIntField(mHealthdConfig->batteryFullChargeDesignCapacityUahPath);
Yifan Hong35cb0832019-10-07 13:58:29 -0700336
Yifan Hongb99d15c2022-03-01 12:12:34 -0800337 mHealthInfo->batteryTemperatureTenthsCelsius =
338 mBatteryFixedTemperature ? mBatteryFixedTemperature
339 : getIntField(mHealthdConfig->batteryTemperaturePath);
Todd Poynor752faf22013-06-12 13:25:59 -0700340
Michael Scott3217c5c2016-06-05 11:20:13 -0700341 std::string buf;
Todd Poynor752faf22013-06-12 13:25:59 -0700342
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800343 if (readFromFile(mHealthdConfig->batteryCapacityLevelPath, &buf) > 0)
344 mHealthInfo->batteryCapacityLevel = getBatteryCapacityLevel(buf.c_str());
345
Michael Scott3217c5c2016-06-05 11:20:13 -0700346 if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
Yifan Hongb99d15c2022-03-01 12:12:34 -0800347 mHealthInfo->batteryStatus = getBatteryStatus(buf.c_str());
Todd Poynor752faf22013-06-12 13:25:59 -0700348
Michael Scott3217c5c2016-06-05 11:20:13 -0700349 if (readFromFile(mHealthdConfig->batteryHealthPath, &buf) > 0)
Yifan Hongb99d15c2022-03-01 12:12:34 -0800350 mHealthInfo->batteryHealth = getBatteryHealth(buf.c_str());
Todd Poynor752faf22013-06-12 13:25:59 -0700351
Michael Scott3217c5c2016-06-05 11:20:13 -0700352 if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
Yifan Hongb99d15c2022-03-01 12:12:34 -0800353 mHealthInfo->batteryTechnology = String8(buf.c_str());
Todd Poynor752faf22013-06-12 13:25:59 -0700354
Badhri Jagan Sridharan40e1df42015-10-27 10:43:53 -0700355 double MaxPower = 0;
Todd Poynor752faf22013-06-12 13:25:59 -0700356
ShevT9d98a6a2018-07-26 11:47:47 +0300357 for (size_t i = 0; i < mChargerNames.size(); i++) {
Todd Poynor752faf22013-06-12 13:25:59 -0700358 String8 path;
359 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
360 mChargerNames[i].string());
Michael Scott3217c5c2016-06-05 11:20:13 -0700361 if (getIntField(path)) {
362 path.clear();
363 path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
364 mChargerNames[i].string());
365 switch(readPowerSupplyType(path)) {
366 case ANDROID_POWER_SUPPLY_TYPE_AC:
Yifan Hongb99d15c2022-03-01 12:12:34 -0800367 mHealthInfo->chargerAcOnline = true;
Michael Scott3217c5c2016-06-05 11:20:13 -0700368 break;
369 case ANDROID_POWER_SUPPLY_TYPE_USB:
Yifan Hongb99d15c2022-03-01 12:12:34 -0800370 mHealthInfo->chargerUsbOnline = true;
Michael Scott3217c5c2016-06-05 11:20:13 -0700371 break;
372 case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
Yifan Hongb99d15c2022-03-01 12:12:34 -0800373 mHealthInfo->chargerWirelessOnline = true;
Michael Scott3217c5c2016-06-05 11:20:13 -0700374 break;
Jack Wu06b90412021-12-15 20:40:21 +0800375 case ANDROID_POWER_SUPPLY_TYPE_DOCK:
Yifan Hongb99d15c2022-03-01 12:12:34 -0800376 mHealthInfo->chargerDockOnline = true;
Jack Wu06b90412021-12-15 20:40:21 +0800377 break;
Michael Scott3217c5c2016-06-05 11:20:13 -0700378 default:
Jack Wu06b90412021-12-15 20:40:21 +0800379 path.clear();
380 path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH,
381 mChargerNames[i].string());
Yifan Hongb99d15c2022-03-01 12:12:34 -0800382 if (access(path.string(), R_OK) == 0)
383 mHealthInfo->chargerDockOnline = true;
384 else
Jack Wu06b90412021-12-15 20:40:21 +0800385 KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
386 mChargerNames[i].string());
Michael Scott3217c5c2016-06-05 11:20:13 -0700387 }
388 path.clear();
389 path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
390 mChargerNames[i].string());
Dmitry Shmidt9f6b80c2016-06-20 12:58:37 -0700391 int ChargingCurrent =
Badhri Jagan Sridharan40e1df42015-10-27 10:43:53 -0700392 (access(path.string(), R_OK) == 0) ? getIntField(path) : 0;
393
Dmitry Shmidt9f6b80c2016-06-20 12:58:37 -0700394 path.clear();
395 path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
396 mChargerNames[i].string());
Badhri Jagan Sridharan40e1df42015-10-27 10:43:53 -0700397
Dmitry Shmidt9f6b80c2016-06-20 12:58:37 -0700398 int ChargingVoltage =
399 (access(path.string(), R_OK) == 0) ? getIntField(path) :
400 DEFAULT_VBUS_VOLTAGE;
Badhri Jagan Sridharan40e1df42015-10-27 10:43:53 -0700401
Dmitry Shmidt9f6b80c2016-06-20 12:58:37 -0700402 double power = ((double)ChargingCurrent / MILLION) *
403 ((double)ChargingVoltage / MILLION);
404 if (MaxPower < power) {
Yifan Hongb99d15c2022-03-01 12:12:34 -0800405 mHealthInfo->maxChargingCurrentMicroamps = ChargingCurrent;
406 mHealthInfo->maxChargingVoltageMicrovolts = ChargingVoltage;
Dmitry Shmidt9f6b80c2016-06-20 12:58:37 -0700407 MaxPower = power;
Todd Poynor752faf22013-06-12 13:25:59 -0700408 }
409 }
410 }
Yifan Hong1353e702019-10-07 10:41:30 -0700411}
Todd Poynor752faf22013-06-12 13:25:59 -0700412
Yifan Hong1353e702019-10-07 10:41:30 -0700413void BatteryMonitor::logValues(void) {
Yifan Hong605e7d22021-02-08 15:14:48 -0800414 logValues(*mHealthInfo, *mHealthdConfig);
415}
416
Yifan Hongb99d15c2022-03-01 12:12:34 -0800417void BatteryMonitor::logValues(const HealthInfo_2_1& health_info,
418 const struct healthd_config& healthd_config) {
419 HealthInfo aidl_health_info;
420 (void)android::h2a::translate(health_info, &aidl_health_info);
421 logValues(aidl_health_info, healthd_config);
422}
423
424void BatteryMonitor::logValues(const HealthInfo& props,
Yifan Hong605e7d22021-02-08 15:14:48 -0800425 const struct healthd_config& healthd_config) {
Yifan Hong1353e702019-10-07 10:41:30 -0700426 char dmesgline[256];
427 size_t len;
428 if (props.batteryPresent) {
429 snprintf(dmesgline, sizeof(dmesgline), "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
Yifan Hongb99d15c2022-03-01 12:12:34 -0800430 props.batteryLevel, props.batteryVoltageMillivolts,
431 props.batteryTemperatureTenthsCelsius < 0 ? "-" : "",
432 abs(props.batteryTemperatureTenthsCelsius / 10),
433 abs(props.batteryTemperatureTenthsCelsius % 10), props.batteryHealth,
434 props.batteryStatus);
Todd Poynorb45f1f52013-07-30 18:57:16 -0700435
Yifan Hong1353e702019-10-07 10:41:30 -0700436 len = strlen(dmesgline);
Yifan Hong605e7d22021-02-08 15:14:48 -0800437 if (!healthd_config.batteryCurrentNowPath.isEmpty()) {
Yifan Hong1353e702019-10-07 10:41:30 -0700438 len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " c=%d",
Yifan Hongb99d15c2022-03-01 12:12:34 -0800439 props.batteryCurrentMicroamps);
Todd Poynor10b235e2013-08-07 15:25:14 -0700440 }
441
Yifan Hong605e7d22021-02-08 15:14:48 -0800442 if (!healthd_config.batteryFullChargePath.isEmpty()) {
Yifan Hong1353e702019-10-07 10:41:30 -0700443 len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " fc=%d",
Yifan Hongb99d15c2022-03-01 12:12:34 -0800444 props.batteryFullChargeUah);
Yifan Hong1353e702019-10-07 10:41:30 -0700445 }
Mark Salyzynacb1ddf2015-07-23 09:22:50 -0700446
Yifan Hong605e7d22021-02-08 15:14:48 -0800447 if (!healthd_config.batteryCycleCountPath.isEmpty()) {
Yifan Hong1353e702019-10-07 10:41:30 -0700448 len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " cc=%d",
449 props.batteryCycleCount);
450 }
451 } else {
452 len = snprintf(dmesgline, sizeof(dmesgline), "battery none");
Todd Poynorb45f1f52013-07-30 18:57:16 -0700453 }
454
Yifan Hongb99d15c2022-03-01 12:12:34 -0800455 snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s%s",
Yifan Hong1353e702019-10-07 10:41:30 -0700456 props.chargerAcOnline ? "a" : "", props.chargerUsbOnline ? "u" : "",
Yifan Hongb99d15c2022-03-01 12:12:34 -0800457 props.chargerWirelessOnline ? "w" : "", props.chargerDockOnline ? "d" : "");
Yifan Hong1353e702019-10-07 10:41:30 -0700458
459 KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
460}
461
462bool BatteryMonitor::isChargerOnline() {
Yifan Hongb99d15c2022-03-01 12:12:34 -0800463 const HealthInfo& props = *mHealthInfo;
Jack Wu06b90412021-12-15 20:40:21 +0800464 return props.chargerAcOnline | props.chargerUsbOnline | props.chargerWirelessOnline |
Yifan Hongb99d15c2022-03-01 12:12:34 -0800465 props.chargerDockOnline;
Todd Poynor752faf22013-06-12 13:25:59 -0700466}
467
Yabin Cuiaedf6032016-02-19 18:03:23 -0800468int BatteryMonitor::getChargeStatus() {
Yifan Hong1d4368b2019-10-07 11:18:04 -0700469 BatteryStatus result = BatteryStatus::UNKNOWN;
Yabin Cuiaedf6032016-02-19 18:03:23 -0800470 if (!mHealthdConfig->batteryStatusPath.isEmpty()) {
Michael Scott3217c5c2016-06-05 11:20:13 -0700471 std::string buf;
472 if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
473 result = getBatteryStatus(buf.c_str());
Yabin Cuiaedf6032016-02-19 18:03:23 -0800474 }
Yifan Hong1d4368b2019-10-07 11:18:04 -0700475 return static_cast<int>(result);
Yabin Cuiaedf6032016-02-19 18:03:23 -0800476}
477
Todd Poynorc133b712013-08-14 17:39:13 -0700478status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
479 status_t ret = BAD_VALUE;
Jin Qian72adf112017-02-02 17:31:13 -0800480 std::string buf;
Todd Poynorc133b712013-08-14 17:39:13 -0700481
Todd Poynor8f132af2014-05-08 17:15:45 -0700482 val->valueInt64 = LONG_MIN;
483
Todd Poynorc133b712013-08-14 17:39:13 -0700484 switch(id) {
485 case BATTERY_PROP_CHARGE_COUNTER:
486 if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
Todd Poynor8f132af2014-05-08 17:15:45 -0700487 val->valueInt64 =
Todd Poynorc133b712013-08-14 17:39:13 -0700488 getIntField(mHealthdConfig->batteryChargeCounterPath);
Elliott Hughes643268f2018-10-08 11:10:11 -0700489 ret = OK;
Todd Poynorc133b712013-08-14 17:39:13 -0700490 } else {
491 ret = NAME_NOT_FOUND;
492 }
493 break;
494
495 case BATTERY_PROP_CURRENT_NOW:
496 if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
Todd Poynor8f132af2014-05-08 17:15:45 -0700497 val->valueInt64 =
Todd Poynorc133b712013-08-14 17:39:13 -0700498 getIntField(mHealthdConfig->batteryCurrentNowPath);
Elliott Hughes643268f2018-10-08 11:10:11 -0700499 ret = OK;
Todd Poynorc133b712013-08-14 17:39:13 -0700500 } else {
501 ret = NAME_NOT_FOUND;
502 }
503 break;
504
Todd Poynorbc102112013-08-27 18:11:49 -0700505 case BATTERY_PROP_CURRENT_AVG:
506 if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
Todd Poynor8f132af2014-05-08 17:15:45 -0700507 val->valueInt64 =
Todd Poynorbc102112013-08-27 18:11:49 -0700508 getIntField(mHealthdConfig->batteryCurrentAvgPath);
Elliott Hughes643268f2018-10-08 11:10:11 -0700509 ret = OK;
Todd Poynorbc102112013-08-27 18:11:49 -0700510 } else {
511 ret = NAME_NOT_FOUND;
512 }
513 break;
514
Paul Lawrence347c8de2014-03-19 15:04:40 -0700515 case BATTERY_PROP_CAPACITY:
516 if (!mHealthdConfig->batteryCapacityPath.isEmpty()) {
Todd Poynor8f132af2014-05-08 17:15:45 -0700517 val->valueInt64 =
Paul Lawrence347c8de2014-03-19 15:04:40 -0700518 getIntField(mHealthdConfig->batteryCapacityPath);
Elliott Hughes643268f2018-10-08 11:10:11 -0700519 ret = OK;
Paul Lawrence347c8de2014-03-19 15:04:40 -0700520 } else {
521 ret = NAME_NOT_FOUND;
522 }
523 break;
524
Todd Poynor8f132af2014-05-08 17:15:45 -0700525 case BATTERY_PROP_ENERGY_COUNTER:
Todd Poynore14b37e2014-05-20 13:54:40 -0700526 if (mHealthdConfig->energyCounter) {
527 ret = mHealthdConfig->energyCounter(&val->valueInt64);
528 } else {
529 ret = NAME_NOT_FOUND;
530 }
Todd Poynor8f132af2014-05-08 17:15:45 -0700531 break;
532
Jin Qian72adf112017-02-02 17:31:13 -0800533 case BATTERY_PROP_BATTERY_STATUS:
Todd Poynore030a102018-01-19 14:03:59 -0800534 val->valueInt64 = getChargeStatus();
Elliott Hughes643268f2018-10-08 11:10:11 -0700535 ret = OK;
Jin Qian72adf112017-02-02 17:31:13 -0800536 break;
537
Todd Poynorc133b712013-08-14 17:39:13 -0700538 default:
539 break;
540 }
541
Todd Poynorc133b712013-08-14 17:39:13 -0700542 return ret;
543}
544
Todd Poynor020369d2013-09-18 20:09:33 -0700545void BatteryMonitor::dumpState(int fd) {
546 int v;
547 char vs[128];
Yifan Hongb99d15c2022-03-01 12:12:34 -0800548 const HealthInfo& props = *mHealthInfo;
Todd Poynor020369d2013-09-18 20:09:33 -0700549
Jack Wu06b90412021-12-15 20:40:21 +0800550 snprintf(vs, sizeof(vs),
551 "ac: %d usb: %d wireless: %d dock: %d current_max: %d voltage_max: %d\n",
552 props.chargerAcOnline, props.chargerUsbOnline, props.chargerWirelessOnline,
Yifan Hongb99d15c2022-03-01 12:12:34 -0800553 props.chargerDockOnline, props.maxChargingCurrentMicroamps,
554 props.maxChargingVoltageMicrovolts);
Todd Poynor020369d2013-09-18 20:09:33 -0700555 write(fd, vs, strlen(vs));
556 snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
557 props.batteryStatus, props.batteryHealth, props.batteryPresent);
558 write(fd, vs, strlen(vs));
Yifan Hongb99d15c2022-03-01 12:12:34 -0800559 snprintf(vs, sizeof(vs), "level: %d voltage: %d temp: %d\n", props.batteryLevel,
560 props.batteryVoltageMillivolts, props.batteryTemperatureTenthsCelsius);
Todd Poynor020369d2013-09-18 20:09:33 -0700561 write(fd, vs, strlen(vs));
562
563 if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
564 v = getIntField(mHealthdConfig->batteryCurrentNowPath);
565 snprintf(vs, sizeof(vs), "current now: %d\n", v);
566 write(fd, vs, strlen(vs));
567 }
568
569 if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
570 v = getIntField(mHealthdConfig->batteryCurrentAvgPath);
571 snprintf(vs, sizeof(vs), "current avg: %d\n", v);
572 write(fd, vs, strlen(vs));
573 }
574
575 if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
576 v = getIntField(mHealthdConfig->batteryChargeCounterPath);
577 snprintf(vs, sizeof(vs), "charge counter: %d\n", v);
578 write(fd, vs, strlen(vs));
579 }
Ruchi Kandoicc338802015-08-24 13:01:16 -0700580
581 if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
Yifan Hongb99d15c2022-03-01 12:12:34 -0800582 snprintf(vs, sizeof(vs), "current now: %d\n", props.batteryCurrentMicroamps);
Ruchi Kandoicc338802015-08-24 13:01:16 -0700583 write(fd, vs, strlen(vs));
584 }
585
586 if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
587 snprintf(vs, sizeof(vs), "cycle count: %d\n", props.batteryCycleCount);
588 write(fd, vs, strlen(vs));
589 }
590
591 if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
Yifan Hongb99d15c2022-03-01 12:12:34 -0800592 snprintf(vs, sizeof(vs), "Full charge: %d\n", props.batteryFullChargeUah);
Ruchi Kandoicc338802015-08-24 13:01:16 -0700593 write(fd, vs, strlen(vs));
594 }
Todd Poynor020369d2013-09-18 20:09:33 -0700595}
596
Todd Poynorc7464c92013-09-10 12:40:00 -0700597void BatteryMonitor::init(struct healthd_config *hc) {
Todd Poynor752faf22013-06-12 13:25:59 -0700598 String8 path;
Todd Poynor3db03a52014-05-21 16:28:13 -0700599 char pval[PROPERTY_VALUE_MAX];
Todd Poynor752faf22013-06-12 13:25:59 -0700600
Todd Poynorf5d30122013-08-12 17:03:35 -0700601 mHealthdConfig = hc;
James Hawkins588a2ca2016-02-18 14:52:46 -0800602 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir);
Todd Poynor752faf22013-06-12 13:25:59 -0700603 if (dir == NULL) {
604 KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
605 } else {
606 struct dirent* entry;
607
James Hawkins588a2ca2016-02-18 14:52:46 -0800608 while ((entry = readdir(dir.get()))) {
Todd Poynor752faf22013-06-12 13:25:59 -0700609 const char* name = entry->d_name;
610
611 if (!strcmp(name, ".") || !strcmp(name, ".."))
612 continue;
613
Bart Van Assche25b2a8d2022-02-24 21:51:34 +0000614 std::vector<String8>::iterator itIgnoreName =
615 find(hc->ignorePowerSupplyNames.begin(), hc->ignorePowerSupplyNames.end(),
616 String8(name));
Thierry Strudelf73de6f2019-01-11 17:09:20 -0800617 if (itIgnoreName != hc->ignorePowerSupplyNames.end())
618 continue;
619
Todd Poynor752faf22013-06-12 13:25:59 -0700620 // Look for "type" file in each subdirectory
621 path.clear();
622 path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
623 switch(readPowerSupplyType(path)) {
624 case ANDROID_POWER_SUPPLY_TYPE_AC:
625 case ANDROID_POWER_SUPPLY_TYPE_USB:
626 case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
Jack Wu06b90412021-12-15 20:40:21 +0800627 case ANDROID_POWER_SUPPLY_TYPE_DOCK:
Todd Poynor752faf22013-06-12 13:25:59 -0700628 path.clear();
629 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
630 if (access(path.string(), R_OK) == 0)
631 mChargerNames.add(String8(name));
632 break;
633
634 case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
Kazuhiro Inaba8e4d9822019-06-12 13:46:08 +0900635 // Some devices expose the battery status of sub-component like
636 // stylus. Such a device-scoped battery info needs to be skipped
637 // in BatteryMonitor, which is intended to report the status of
638 // the battery supplying the power to the whole system.
639 if (isScopedPowerSupply(name)) continue;
Todd Poynor6dcc45e2013-10-21 20:26:25 -0700640 mBatteryDevicePresent = true;
641
Todd Poynorf5d30122013-08-12 17:03:35 -0700642 if (mHealthdConfig->batteryStatusPath.isEmpty()) {
Todd Poynor752faf22013-06-12 13:25:59 -0700643 path.clear();
Todd Poynorf5d30122013-08-12 17:03:35 -0700644 path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
645 name);
Todd Poynor752faf22013-06-12 13:25:59 -0700646 if (access(path, R_OK) == 0)
Todd Poynorf5d30122013-08-12 17:03:35 -0700647 mHealthdConfig->batteryStatusPath = path;
Todd Poynor752faf22013-06-12 13:25:59 -0700648 }
649
Todd Poynorf5d30122013-08-12 17:03:35 -0700650 if (mHealthdConfig->batteryHealthPath.isEmpty()) {
Todd Poynor752faf22013-06-12 13:25:59 -0700651 path.clear();
Todd Poynorf5d30122013-08-12 17:03:35 -0700652 path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
653 name);
Todd Poynor752faf22013-06-12 13:25:59 -0700654 if (access(path, R_OK) == 0)
Todd Poynorf5d30122013-08-12 17:03:35 -0700655 mHealthdConfig->batteryHealthPath = path;
Todd Poynor752faf22013-06-12 13:25:59 -0700656 }
657
Todd Poynorf5d30122013-08-12 17:03:35 -0700658 if (mHealthdConfig->batteryPresentPath.isEmpty()) {
659 path.clear();
660 path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
661 name);
662 if (access(path, R_OK) == 0)
663 mHealthdConfig->batteryPresentPath = path;
664 }
665
666 if (mHealthdConfig->batteryCapacityPath.isEmpty()) {
667 path.clear();
668 path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
669 name);
670 if (access(path, R_OK) == 0)
671 mHealthdConfig->batteryCapacityPath = path;
672 }
673
674 if (mHealthdConfig->batteryVoltagePath.isEmpty()) {
675 path.clear();
676 path.appendFormat("%s/%s/voltage_now",
677 POWER_SUPPLY_SYSFS_PATH, name);
678 if (access(path, R_OK) == 0) {
679 mHealthdConfig->batteryVoltagePath = path;
Todd Poynorf5d30122013-08-12 17:03:35 -0700680 }
681 }
682
Ruchi Kandoicc338802015-08-24 13:01:16 -0700683 if (mHealthdConfig->batteryFullChargePath.isEmpty()) {
684 path.clear();
685 path.appendFormat("%s/%s/charge_full",
686 POWER_SUPPLY_SYSFS_PATH, name);
687 if (access(path, R_OK) == 0)
688 mHealthdConfig->batteryFullChargePath = path;
689 }
690
Todd Poynorf5d30122013-08-12 17:03:35 -0700691 if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
692 path.clear();
693 path.appendFormat("%s/%s/current_now",
694 POWER_SUPPLY_SYSFS_PATH, name);
695 if (access(path, R_OK) == 0)
696 mHealthdConfig->batteryCurrentNowPath = path;
697 }
698
Ruchi Kandoicc338802015-08-24 13:01:16 -0700699 if (mHealthdConfig->batteryCycleCountPath.isEmpty()) {
700 path.clear();
701 path.appendFormat("%s/%s/cycle_count",
702 POWER_SUPPLY_SYSFS_PATH, name);
703 if (access(path, R_OK) == 0)
704 mHealthdConfig->batteryCycleCountPath = path;
705 }
706
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800707 if (mHealthdConfig->batteryCapacityLevelPath.isEmpty()) {
708 path.clear();
709 path.appendFormat("%s/%s/capacity_level", POWER_SUPPLY_SYSFS_PATH, name);
710 if (access(path, R_OK) == 0) mHealthdConfig->batteryCapacityLevelPath = path;
711 }
712
713 if (mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty()) {
714 path.clear();
715 path.appendFormat("%s/%s/time_to_full_now", POWER_SUPPLY_SYSFS_PATH, name);
716 if (access(path, R_OK) == 0)
717 mHealthdConfig->batteryChargeTimeToFullNowPath = path;
718 }
719
Stephane Lee1c108ed2020-02-10 18:23:57 -0800720 if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty()) {
721 path.clear();
722 path.appendFormat("%s/%s/charge_full_design", POWER_SUPPLY_SYSFS_PATH, name);
723 if (access(path, R_OK) == 0)
724 mHealthdConfig->batteryFullChargeDesignCapacityUahPath = path;
725 }
726
Todd Poynorbc102112013-08-27 18:11:49 -0700727 if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
728 path.clear();
729 path.appendFormat("%s/%s/current_avg",
730 POWER_SUPPLY_SYSFS_PATH, name);
731 if (access(path, R_OK) == 0)
732 mHealthdConfig->batteryCurrentAvgPath = path;
733 }
734
Todd Poynorf5d30122013-08-12 17:03:35 -0700735 if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
736 path.clear();
737 path.appendFormat("%s/%s/charge_counter",
738 POWER_SUPPLY_SYSFS_PATH, name);
739 if (access(path, R_OK) == 0)
740 mHealthdConfig->batteryChargeCounterPath = path;
741 }
742
743 if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
744 path.clear();
745 path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
746 name);
747 if (access(path, R_OK) == 0) {
748 mHealthdConfig->batteryTemperaturePath = path;
Todd Poynorf5d30122013-08-12 17:03:35 -0700749 }
750 }
751
752 if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {
753 path.clear();
754 path.appendFormat("%s/%s/technology",
755 POWER_SUPPLY_SYSFS_PATH, name);
756 if (access(path, R_OK) == 0)
757 mHealthdConfig->batteryTechnologyPath = path;
758 }
759
Todd Poynor752faf22013-06-12 13:25:59 -0700760 break;
761
762 case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
763 break;
764 }
Jack Wu06b90412021-12-15 20:40:21 +0800765
766 // Look for "is_dock" file
767 path.clear();
768 path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH, name);
769 if (access(path.string(), R_OK) == 0) {
770 path.clear();
771 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
772 if (access(path.string(), R_OK) == 0)
773 mChargerNames.add(String8(name));
774
775 }
Todd Poynor752faf22013-06-12 13:25:59 -0700776 }
Todd Poynor752faf22013-06-12 13:25:59 -0700777 }
778
Ian Pedowitz585ab652015-10-12 19:01:00 -0700779 // Typically the case for devices which do not have a battery and
780 // and are always plugged into AC mains.
Todd Poynor6dcc45e2013-10-21 20:26:25 -0700781 if (!mBatteryDevicePresent) {
Todd Poynorebeb0c02014-09-23 14:54:24 -0700782 KLOG_WARNING(LOG_TAG, "No battery devices found\n");
Todd Poynor6dcc45e2013-10-21 20:26:25 -0700783 hc->periodic_chores_interval_fast = -1;
784 hc->periodic_chores_interval_slow = -1;
785 } else {
786 if (mHealthdConfig->batteryStatusPath.isEmpty())
787 KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
788 if (mHealthdConfig->batteryHealthPath.isEmpty())
789 KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");
790 if (mHealthdConfig->batteryPresentPath.isEmpty())
791 KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
792 if (mHealthdConfig->batteryCapacityPath.isEmpty())
793 KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
794 if (mHealthdConfig->batteryVoltagePath.isEmpty())
795 KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
796 if (mHealthdConfig->batteryTemperaturePath.isEmpty())
797 KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
798 if (mHealthdConfig->batteryTechnologyPath.isEmpty())
799 KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
Ruchi Kandoif18ec9f2015-09-28 13:35:59 -0700800 if (mHealthdConfig->batteryCurrentNowPath.isEmpty())
Ruchi Kandoicc338802015-08-24 13:01:16 -0700801 KLOG_WARNING(LOG_TAG, "BatteryCurrentNowPath not found\n");
802 if (mHealthdConfig->batteryFullChargePath.isEmpty())
803 KLOG_WARNING(LOG_TAG, "BatteryFullChargePath not found\n");
804 if (mHealthdConfig->batteryCycleCountPath.isEmpty())
805 KLOG_WARNING(LOG_TAG, "BatteryCycleCountPath not found\n");
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800806 if (mHealthdConfig->batteryCapacityLevelPath.isEmpty())
807 KLOG_WARNING(LOG_TAG, "batteryCapacityLevelPath not found\n");
808 if (mHealthdConfig->batteryChargeTimeToFullNowPath.isEmpty())
809 KLOG_WARNING(LOG_TAG, "batteryChargeTimeToFullNowPath. not found\n");
Stephane Lee1c108ed2020-02-10 18:23:57 -0800810 if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.isEmpty())
811 KLOG_WARNING(LOG_TAG, "batteryFullChargeDesignCapacityUahPath. not found\n");
Todd Poynor6dcc45e2013-10-21 20:26:25 -0700812 }
Todd Poynor3db03a52014-05-21 16:28:13 -0700813
Ruchi Kandoia78fc232014-07-10 15:06:21 -0700814 if (property_get("ro.boot.fake_battery", pval, NULL) > 0
815 && strtol(pval, NULL, 10) != 0) {
816 mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;
817 mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
818 }
Todd Poynor752faf22013-06-12 13:25:59 -0700819}
820
821}; // namespace android