blob: 62f50b33a57e32d007699d89116ded28edd2c956 [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;
Jack Wue561d032022-11-24 12:19:41 +080058using aidl::android::hardware::health::BatteryChargingPolicy;
59using aidl::android::hardware::health::BatteryChargingState;
Yifan Hongb99d15c2022-03-01 12:12:34 -080060using aidl::android::hardware::health::BatteryHealth;
Jack Wue561d032022-11-24 12:19:41 +080061using aidl::android::hardware::health::BatteryHealthData;
David Andersond5ed26a2023-12-08 15:12:24 -080062using aidl::android::hardware::health::BatteryPartStatus;
Yifan Hongb99d15c2022-03-01 12:12:34 -080063using aidl::android::hardware::health::BatteryStatus;
64using aidl::android::hardware::health::HealthInfo;
65
66namespace {
67
68// Translate from AIDL back to HIDL definition for getHealthInfo_*_* calls.
69// Skips storageInfo and diskStats.
70void 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
92void 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
99void 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
Yifan Hong1d4368b2019-10-07 11:18:04 -0700109
Todd Poynor752faf22013-06-12 13:25:59 -0700110namespace android {
111
Yifan Hong1d4368b2019-10-07 11:18:04 -0700112template <typename T>
113struct SysfsStringEnumMap {
Mark Salyzyn6f5b47f2014-05-15 15:00:59 -0700114 const char* s;
Yifan Hong1d4368b2019-10-07 11:18:04 -0700115 T val;
Todd Poynor752faf22013-06-12 13:25:59 -0700116};
117
Yifan Hong1d4368b2019-10-07 11:18:04 -0700118template <typename T>
119static std::optional<T> mapSysfsString(const char* str, SysfsStringEnumMap<T> map[]) {
Todd Poynor752faf22013-06-12 13:25:59 -0700120 for (int i = 0; map[i].s; i++)
121 if (!strcmp(str, map[i].s))
122 return map[i].val;
123
Yifan Hong1d4368b2019-10-07 11:18:04 -0700124 return std::nullopt;
Yabin Cuidb04a492016-02-16 17:19:23 -0800125}
126
Yifan Hongb99d15c2022-03-01 12:12:34 -0800127static void initHealthInfo(HealthInfo* health_info) {
Bart Van Assche024e18f2022-02-24 21:22:07 +0000128 *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,
Andrei Ciubotariu515f5b52025-02-12 21:31:23 -0800134 .batteryHealthData = std::nullopt,
Bart Van Assche024e18f2022-02-24 21:22:07 +0000135 };
Yifan Hong6cabe9b2019-11-05 17:04:50 -0800136}
137
Todd Poynore030a102018-01-19 14:03:59 -0800138BatteryMonitor::BatteryMonitor()
139 : mHealthdConfig(nullptr),
140 mBatteryDevicePresent(false),
141 mBatteryFixedCapacity(0),
Yifan Hong1d4368b2019-10-07 11:18:04 -0700142 mBatteryFixedTemperature(0),
Jack Wub57f68a2023-02-04 19:56:06 +0800143 mBatteryHealthStatus(BatteryMonitor::BH_UNKNOWN),
Yifan Hongb99d15c2022-03-01 12:12:34 -0800144 mHealthInfo(std::make_unique<HealthInfo>()) {
Yifan Hong6cabe9b2019-11-05 17:04:50 -0800145 initHealthInfo(mHealthInfo.get());
146}
Yifan Hong1d4368b2019-10-07 11:18:04 -0700147
148BatteryMonitor::~BatteryMonitor() {}
149
Yifan Hongb99d15c2022-03-01 12:12:34 -0800150HealthInfo_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;
Yabin Cuidb04a492016-02-16 17:19:23 -0800154}
155
Yifan Hongb99d15c2022-03-01 12:12:34 -0800156HealthInfo_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;
Hridya Valsaraju7fa72252018-01-12 17:44:33 -0800160}
161
Yifan Hongb99d15c2022-03-01 12:12:34 -0800162HealthInfo_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
168const HealthInfo& BatteryMonitor::getHealthInfo() const {
Yifan Hong1d4368b2019-10-07 11:18:04 -0700169 return *mHealthInfo;
170}
171
172BatteryStatus 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},
Todd Poynor752faf22013-06-12 13:25:59 -0700180 };
181
Yifan Hong1d4368b2019-10-07 11:18:04 -0700182 auto ret = mapSysfsString(status, batteryStatusMap);
183 if (!ret) {
Todd Poynor752faf22013-06-12 13:25:59 -0700184 KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
Yifan Hong1d4368b2019-10-07 11:18:04 -0700185 *ret = BatteryStatus::UNKNOWN;
Todd Poynor752faf22013-06-12 13:25:59 -0700186 }
187
Yifan Hong1d4368b2019-10-07 11:18:04 -0700188 return *ret;
Todd Poynor752faf22013-06-12 13:25:59 -0700189}
190
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800191BatteryCapacityLevel 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},
Stephane Lee06846042020-02-12 17:00:24 -0800199 {NULL, BatteryCapacityLevel::UNSUPPORTED},
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800200 };
201
202 auto ret = mapSysfsString(capacityLevel, batteryCapacityLevelMap);
203 if (!ret) {
Stephane Lee06846042020-02-12 17:00:24 -0800204 KLOG_WARNING(LOG_TAG, "Unsupported battery capacity level '%s'\n", capacityLevel);
205 *ret = BatteryCapacityLevel::UNSUPPORTED;
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800206 }
207
208 return *ret;
209}
210
Yifan Hong1d4368b2019-10-07 11:18:04 -0700211BatteryHealth 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},
David Anderson629a26b2023-12-11 15:25:13 -0800224 {"Calibration required", BatteryHealth::INCONSISTENT},
Yifan Hong1d4368b2019-10-07 11:18:04 -0700225 {NULL, BatteryHealth::UNKNOWN},
Todd Poynor752faf22013-06-12 13:25:59 -0700226 };
227
Yifan Hong1d4368b2019-10-07 11:18:04 -0700228 auto ret = mapSysfsString(status, batteryHealthMap);
229 if (!ret) {
Todd Poynor752faf22013-06-12 13:25:59 -0700230 KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
Yifan Hong1d4368b2019-10-07 11:18:04 -0700231 *ret = BatteryHealth::UNKNOWN;
Todd Poynor752faf22013-06-12 13:25:59 -0700232 }
233
Yifan Hong1d4368b2019-10-07 11:18:04 -0700234 return *ret;
Todd Poynor752faf22013-06-12 13:25:59 -0700235}
236
Jack Wub57f68a2023-02-04 19:56:06 +0800237BatteryHealth 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;
Jack Wucf996f32023-04-13 19:37:46 +0800248 else if (status == BatteryMonitor::BH_NOT_AVAILABLE)
249 value = BatteryHealth::NOT_AVAILABLE;
Jack Wu8231c3f2023-05-19 14:31:53 +0800250 else if (status == BatteryMonitor::BH_INCONSISTENT)
251 value = BatteryHealth::INCONSISTENT;
Jack Wub57f68a2023-02-04 19:56:06 +0800252 else
253 value = BatteryHealth::UNKNOWN;
254
255 return value;
256}
257
Jack Wue561d032022-11-24 12:19:41 +0800258BatteryChargingPolicy 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
273BatteryChargingState 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
Bart Van Assche095c9442022-03-02 17:36:34 +0000289static int readFromFile(const String8& path, std::string* buf) {
Bart Van Assche5a7e5082022-02-24 21:40:15 +0000290 buf->clear();
Steven Moreland2aac3352017-03-10 22:31:08 -0800291 if (android::base::ReadFileToString(path.c_str(), buf)) {
Michael Scott3217c5c2016-06-05 11:20:13 -0700292 *buf = android::base::Trim(*buf);
Todd Poynor752faf22013-06-12 13:25:59 -0700293 }
Michael Scott3217c5c2016-06-05 11:20:13 -0700294 return buf->length();
Todd Poynor752faf22013-06-12 13:25:59 -0700295}
296
Jack Wue561d032022-11-24 12:19:41 +0800297static bool writeToFile(const String8& path, int32_t in_value) {
298 return android::base::WriteStringToFile(std::to_string(in_value), path.c_str());
299}
300
Bart Van Assche095c9442022-03-02 17:36:34 +0000301static BatteryMonitor::PowerSupplyType readPowerSupplyType(const String8& path) {
Yifan Hong1d4368b2019-10-07 11:18:04 -0700302 static SysfsStringEnumMap<int> supplyTypeMap[] = {
Bart Van Assche095c9442022-03-02 17:36:34 +0000303 {"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},
Abhijeet Dharmapurikaree19f9f2015-09-14 16:35:26 -0700310 {"USB_HVDCP_3", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
Bart Van Assche095c9442022-03-02 17:36:34 +0000311 {"USB_CDP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
312 {"USB_ACA", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
313 {"USB_C", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
314 {"USB_PD", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
315 {"USB_PD_DRP", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_USB},
316 {"Wireless", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_WIRELESS},
317 {"Dock", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_DOCK},
Abhijeet Dharmapurikaree19f9f2015-09-14 16:35:26 -0700318 {"DASH", BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_AC},
Yifan Hong1d4368b2019-10-07 11:18:04 -0700319 {NULL, 0},
Todd Poynor752faf22013-06-12 13:25:59 -0700320 };
Yifan Hong1d4368b2019-10-07 11:18:04 -0700321 std::string buf;
Todd Poynor752faf22013-06-12 13:25:59 -0700322
Bart Van Assche095c9442022-03-02 17:36:34 +0000323 if (readFromFile(path, &buf) <= 0) {
324 return BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
325 }
Todd Poynor752faf22013-06-12 13:25:59 -0700326
Yifan Hong1d4368b2019-10-07 11:18:04 -0700327 auto ret = mapSysfsString(buf.c_str(), supplyTypeMap);
Abhijeet Dharmapurikar69332482016-05-24 15:12:11 -0700328 if (!ret)
Bart Van Assche095c9442022-03-02 17:36:34 +0000329 *ret = BatteryMonitor::ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
Todd Poynor752faf22013-06-12 13:25:59 -0700330
Yifan Hong1d4368b2019-10-07 11:18:04 -0700331 return static_cast<BatteryMonitor::PowerSupplyType>(*ret);
Todd Poynor752faf22013-06-12 13:25:59 -0700332}
333
Bart Van Assche095c9442022-03-02 17:36:34 +0000334static bool getBooleanField(const String8& path) {
Michael Scott3217c5c2016-06-05 11:20:13 -0700335 std::string buf;
Todd Poynor752faf22013-06-12 13:25:59 -0700336 bool value = false;
Michael Scott3217c5c2016-06-05 11:20:13 -0700337
338 if (readFromFile(path, &buf) > 0)
339 if (buf[0] != '0')
Todd Poynor752faf22013-06-12 13:25:59 -0700340 value = true;
Todd Poynor752faf22013-06-12 13:25:59 -0700341
342 return value;
343}
344
David Andersonebdd01e2025-03-19 02:46:37 +0000345template <typename T = int>
346static T getIntField(const String8& path) {
Michael Scott3217c5c2016-06-05 11:20:13 -0700347 std::string buf;
David Andersonebdd01e2025-03-19 02:46:37 +0000348 T value = 0;
Michael Scott3217c5c2016-06-05 11:20:13 -0700349
350 if (readFromFile(path, &buf) > 0)
Elliott Hughesda46b392016-10-11 17:09:00 -0700351 android::base::ParseInt(buf, &value);
Michael Scott3217c5c2016-06-05 11:20:13 -0700352
Todd Poynor752faf22013-06-12 13:25:59 -0700353 return value;
354}
355
Bart Van Assche095c9442022-03-02 17:36:34 +0000356static bool isScopedPowerSupply(const char* name) {
Kazuhiro Inaba8e4d9822019-06-12 13:46:08 +0900357 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
Andrei Ciubotariu515f5b52025-02-12 21:31:23 -0800365static BatteryHealthData *ensureBatteryHealthData(HealthInfo *info) {
366 if (!info->batteryHealthData.has_value()) {
367 return &info->batteryHealthData.emplace();
368 }
369
370 return &info->batteryHealthData.value();
371}
372
Yifan Hong1353e702019-10-07 10:41:30 -0700373void BatteryMonitor::updateValues(void) {
Yifan Hong6cabe9b2019-11-05 17:04:50 -0800374 initHealthInfo(mHealthInfo.get());
Yifan Hong1d4368b2019-10-07 11:18:04 -0700375
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000376 if (!mHealthdConfig->batteryPresentPath.empty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800377 mHealthInfo->batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
Todd Poynor752faf22013-06-12 13:25:59 -0700378 else
Yifan Hongb99d15c2022-03-01 12:12:34 -0800379 mHealthInfo->batteryPresent = mBatteryDevicePresent;
Todd Poynor752faf22013-06-12 13:25:59 -0700380
Yifan Hongb99d15c2022-03-01 12:12:34 -0800381 mHealthInfo->batteryLevel = mBatteryFixedCapacity
382 ? mBatteryFixedCapacity
383 : getIntField(mHealthdConfig->batteryCapacityPath);
384 mHealthInfo->batteryVoltageMillivolts = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
Todd Poynorb45f1f52013-07-30 18:57:16 -0700385
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000386 if (!mHealthdConfig->batteryCurrentNowPath.empty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800387 mHealthInfo->batteryCurrentMicroamps = getIntField(mHealthdConfig->batteryCurrentNowPath);
Ruchi Kandoicc338802015-08-24 13:01:16 -0700388
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000389 if (!mHealthdConfig->batteryFullChargePath.empty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800390 mHealthInfo->batteryFullChargeUah = getIntField(mHealthdConfig->batteryFullChargePath);
Ruchi Kandoicc338802015-08-24 13:01:16 -0700391
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000392 if (!mHealthdConfig->batteryCycleCountPath.empty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800393 mHealthInfo->batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath);
Ruchi Kandoicc338802015-08-24 13:01:16 -0700394
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000395 if (!mHealthdConfig->batteryChargeCounterPath.empty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800396 mHealthInfo->batteryChargeCounterUah =
397 getIntField(mHealthdConfig->batteryChargeCounterPath);
Ruchi Kandoi3f9886b2016-04-07 12:34:40 -0700398
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000399 if (!mHealthdConfig->batteryCurrentAvgPath.empty())
Yifan Hongb99d15c2022-03-01 12:12:34 -0800400 mHealthInfo->batteryCurrentAverageMicroamps =
Yifan Hong35cb0832019-10-07 13:58:29 -0700401 getIntField(mHealthdConfig->batteryCurrentAvgPath);
402
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000403 if (!mHealthdConfig->batteryChargeTimeToFullNowPath.empty())
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800404 mHealthInfo->batteryChargeTimeToFullNowSeconds =
405 getIntField(mHealthdConfig->batteryChargeTimeToFullNowPath);
406
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000407 if (!mHealthdConfig->batteryFullChargeDesignCapacityUahPath.empty())
Stephane Lee1c108ed2020-02-10 18:23:57 -0800408 mHealthInfo->batteryFullChargeDesignCapacityUah =
409 getIntField(mHealthdConfig->batteryFullChargeDesignCapacityUahPath);
Yifan Hong35cb0832019-10-07 13:58:29 -0700410
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000411 if (!mHealthdConfig->batteryHealthStatusPath.empty())
Jack Wub57f68a2023-02-04 19:56:06 +0800412 mBatteryHealthStatus = getIntField(mHealthdConfig->batteryHealthStatusPath);
413
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000414 if (!mHealthdConfig->batteryStateOfHealthPath.empty())
Andrei Ciubotariu515f5b52025-02-12 21:31:23 -0800415 ensureBatteryHealthData(mHealthInfo.get())->batteryStateOfHealth =
AleX Pelosiff708922023-02-17 01:39:21 +0000416 getIntField(mHealthdConfig->batteryStateOfHealthPath);
417
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000418 if (!mHealthdConfig->batteryManufacturingDatePath.empty())
Andrei Ciubotariu515f5b52025-02-12 21:31:23 -0800419 ensureBatteryHealthData(mHealthInfo.get())->batteryManufacturingDateSeconds =
David Andersonebdd01e2025-03-19 02:46:37 +0000420 getIntField<int64_t>(mHealthdConfig->batteryManufacturingDatePath);
Jack Wue561d032022-11-24 12:19:41 +0800421
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000422 if (!mHealthdConfig->batteryFirstUsageDatePath.empty())
Andrei Ciubotariu515f5b52025-02-12 21:31:23 -0800423 ensureBatteryHealthData(mHealthInfo.get())->batteryFirstUsageSeconds =
David Andersonebdd01e2025-03-19 02:46:37 +0000424 getIntField<int64_t>(mHealthdConfig->batteryFirstUsageDatePath);
Jack Wue561d032022-11-24 12:19:41 +0800425
Yifan Hongb99d15c2022-03-01 12:12:34 -0800426 mHealthInfo->batteryTemperatureTenthsCelsius =
427 mBatteryFixedTemperature ? mBatteryFixedTemperature
428 : getIntField(mHealthdConfig->batteryTemperaturePath);
Todd Poynor752faf22013-06-12 13:25:59 -0700429
Michael Scott3217c5c2016-06-05 11:20:13 -0700430 std::string buf;
Todd Poynor752faf22013-06-12 13:25:59 -0700431
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800432 if (readFromFile(mHealthdConfig->batteryCapacityLevelPath, &buf) > 0)
433 mHealthInfo->batteryCapacityLevel = getBatteryCapacityLevel(buf.c_str());
434
Michael Scott3217c5c2016-06-05 11:20:13 -0700435 if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
Yifan Hongb99d15c2022-03-01 12:12:34 -0800436 mHealthInfo->batteryStatus = getBatteryStatus(buf.c_str());
Todd Poynor752faf22013-06-12 13:25:59 -0700437
Jack Wub57f68a2023-02-04 19:56:06 +0800438 // 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 }
Todd Poynor752faf22013-06-12 13:25:59 -0700445
Michael Scott3217c5c2016-06-05 11:20:13 -0700446 if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000447 mHealthInfo->batteryTechnology = buf;
Todd Poynor752faf22013-06-12 13:25:59 -0700448
Jack Wue561d032022-11-24 12:19:41 +0800449 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
Badhri Jagan Sridharan40e1df42015-10-27 10:43:53 -0700455 double MaxPower = 0;
Todd Poynor752faf22013-06-12 13:25:59 -0700456
Abhijeet Dharmapurikar69332482016-05-24 15:12:11 -0700457 // Rescan for the available charger types
458 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir);
459 if (dir == NULL) {
460 KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
461 } else {
462 struct dirent* entry;
463 String8 path;
464
465 mChargerNames.clear();
466
467 while ((entry = readdir(dir.get()))) {
468 const char* name = entry->d_name;
469
470 if (!strcmp(name, ".") || !strcmp(name, ".."))
471 continue;
472
473 // Look for "type" file in each subdirectory
474 path.clear();
475 path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
476 switch(readPowerSupplyType(path)) {
477 case ANDROID_POWER_SUPPLY_TYPE_AC:
478 case ANDROID_POWER_SUPPLY_TYPE_USB:
479 case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
480 case ANDROID_POWER_SUPPLY_TYPE_DOCK:
481 path.clear();
482 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
Michael Bestas49e82d72024-03-10 18:47:36 +0200483 if (access(path.c_str(), R_OK) == 0)
Abhijeet Dharmapurikar69332482016-05-24 15:12:11 -0700484 mChargerNames.add(String8(name));
485 break;
486 default:
487 break;
488 }
489
490 // Look for "is_dock" file
491 path.clear();
492 path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH, name);
Michael Bestas49e82d72024-03-10 18:47:36 +0200493 if (access(path.c_str(), R_OK) == 0) {
Abhijeet Dharmapurikar69332482016-05-24 15:12:11 -0700494 path.clear();
495 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
Michael Bestas49e82d72024-03-10 18:47:36 +0200496 if (access(path.c_str(), R_OK) == 0)
Abhijeet Dharmapurikar69332482016-05-24 15:12:11 -0700497 mChargerNames.add(String8(name));
498
499 }
500 }
501 }
502
ShevT9d98a6a2018-07-26 11:47:47 +0300503 for (size_t i = 0; i < mChargerNames.size(); i++) {
Todd Poynor752faf22013-06-12 13:25:59 -0700504 String8 path;
Tomasz Wasilczyk18b74612023-08-10 23:29:50 +0000505 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, mChargerNames[i].c_str());
Michael Scott3217c5c2016-06-05 11:20:13 -0700506 if (getIntField(path)) {
507 path.clear();
Tomasz Wasilczyk18b74612023-08-10 23:29:50 +0000508 path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, mChargerNames[i].c_str());
Michael Scott3217c5c2016-06-05 11:20:13 -0700509 switch(readPowerSupplyType(path)) {
510 case ANDROID_POWER_SUPPLY_TYPE_AC:
Yifan Hongb99d15c2022-03-01 12:12:34 -0800511 mHealthInfo->chargerAcOnline = true;
Michael Scott3217c5c2016-06-05 11:20:13 -0700512 break;
513 case ANDROID_POWER_SUPPLY_TYPE_USB:
Yifan Hongb99d15c2022-03-01 12:12:34 -0800514 mHealthInfo->chargerUsbOnline = true;
Michael Scott3217c5c2016-06-05 11:20:13 -0700515 break;
516 case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
Yifan Hongb99d15c2022-03-01 12:12:34 -0800517 mHealthInfo->chargerWirelessOnline = true;
Michael Scott3217c5c2016-06-05 11:20:13 -0700518 break;
Jack Wu06b90412021-12-15 20:40:21 +0800519 case ANDROID_POWER_SUPPLY_TYPE_DOCK:
Yifan Hongb99d15c2022-03-01 12:12:34 -0800520 mHealthInfo->chargerDockOnline = true;
Jack Wu06b90412021-12-15 20:40:21 +0800521 break;
Michael Scott3217c5c2016-06-05 11:20:13 -0700522 default:
Jack Wu06b90412021-12-15 20:40:21 +0800523 path.clear();
524 path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH,
Tomasz Wasilczyk18b74612023-08-10 23:29:50 +0000525 mChargerNames[i].c_str());
526 if (access(path.c_str(), R_OK) == 0)
Yifan Hongb99d15c2022-03-01 12:12:34 -0800527 mHealthInfo->chargerDockOnline = true;
528 else
Jack Wu06b90412021-12-15 20:40:21 +0800529 KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
Tomasz Wasilczyk18b74612023-08-10 23:29:50 +0000530 mChargerNames[i].c_str());
Michael Scott3217c5c2016-06-05 11:20:13 -0700531 }
532 path.clear();
533 path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
Tomasz Wasilczyk18b74612023-08-10 23:29:50 +0000534 mChargerNames[i].c_str());
535 int ChargingCurrent = (access(path.c_str(), R_OK) == 0) ? getIntField(path) : 0;
Badhri Jagan Sridharan40e1df42015-10-27 10:43:53 -0700536
Dmitry Shmidt9f6b80c2016-06-20 12:58:37 -0700537 path.clear();
538 path.appendFormat("%s/%s/voltage_max", POWER_SUPPLY_SYSFS_PATH,
Tomasz Wasilczyk18b74612023-08-10 23:29:50 +0000539 mChargerNames[i].c_str());
Badhri Jagan Sridharan40e1df42015-10-27 10:43:53 -0700540
Dmitry Shmidt9f6b80c2016-06-20 12:58:37 -0700541 int ChargingVoltage =
Tomasz Wasilczyk18b74612023-08-10 23:29:50 +0000542 (access(path.c_str(), R_OK) == 0) ? getIntField(path) : DEFAULT_VBUS_VOLTAGE;
Badhri Jagan Sridharan40e1df42015-10-27 10:43:53 -0700543
Dmitry Shmidt9f6b80c2016-06-20 12:58:37 -0700544 double power = ((double)ChargingCurrent / MILLION) *
545 ((double)ChargingVoltage / MILLION);
546 if (MaxPower < power) {
Yifan Hongb99d15c2022-03-01 12:12:34 -0800547 mHealthInfo->maxChargingCurrentMicroamps = ChargingCurrent;
548 mHealthInfo->maxChargingVoltageMicrovolts = ChargingVoltage;
Dmitry Shmidt9f6b80c2016-06-20 12:58:37 -0700549 MaxPower = power;
Todd Poynor752faf22013-06-12 13:25:59 -0700550 }
551 }
552 }
Yifan Hong1353e702019-10-07 10:41:30 -0700553}
Todd Poynor752faf22013-06-12 13:25:59 -0700554
Bart Van Assche095c9442022-03-02 17:36:34 +0000555static void doLogValues(const HealthInfo& props, const struct healthd_config& healthd_config) {
Yifan Hong1353e702019-10-07 10:41:30 -0700556 char dmesgline[256];
557 size_t len;
558 if (props.batteryPresent) {
559 snprintf(dmesgline, sizeof(dmesgline), "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
Yifan Hongb99d15c2022-03-01 12:12:34 -0800560 props.batteryLevel, props.batteryVoltageMillivolts,
561 props.batteryTemperatureTenthsCelsius < 0 ? "-" : "",
562 abs(props.batteryTemperatureTenthsCelsius / 10),
563 abs(props.batteryTemperatureTenthsCelsius % 10), props.batteryHealth,
564 props.batteryStatus);
Todd Poynorb45f1f52013-07-30 18:57:16 -0700565
Yifan Hong1353e702019-10-07 10:41:30 -0700566 len = strlen(dmesgline);
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000567 if (!healthd_config.batteryCurrentNowPath.empty()) {
Yifan Hong1353e702019-10-07 10:41:30 -0700568 len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " c=%d",
Yifan Hongb99d15c2022-03-01 12:12:34 -0800569 props.batteryCurrentMicroamps);
Todd Poynor10b235e2013-08-07 15:25:14 -0700570 }
571
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000572 if (!healthd_config.batteryFullChargePath.empty()) {
Yifan Hong1353e702019-10-07 10:41:30 -0700573 len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " fc=%d",
Yifan Hongb99d15c2022-03-01 12:12:34 -0800574 props.batteryFullChargeUah);
Yifan Hong1353e702019-10-07 10:41:30 -0700575 }
Mark Salyzynacb1ddf2015-07-23 09:22:50 -0700576
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000577 if (!healthd_config.batteryCycleCountPath.empty()) {
Yifan Hong1353e702019-10-07 10:41:30 -0700578 len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " cc=%d",
579 props.batteryCycleCount);
580 }
581 } else {
582 len = snprintf(dmesgline, sizeof(dmesgline), "battery none");
Todd Poynorb45f1f52013-07-30 18:57:16 -0700583 }
584
Yifan Hongb99d15c2022-03-01 12:12:34 -0800585 snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s%s",
Yifan Hong1353e702019-10-07 10:41:30 -0700586 props.chargerAcOnline ? "a" : "", props.chargerUsbOnline ? "u" : "",
Yifan Hongb99d15c2022-03-01 12:12:34 -0800587 props.chargerWirelessOnline ? "w" : "", props.chargerDockOnline ? "d" : "");
Yifan Hong1353e702019-10-07 10:41:30 -0700588
AleX Pelosif08aede2024-02-15 18:42:11 +0000589 KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
Yifan Hong1353e702019-10-07 10:41:30 -0700590}
591
Bart Van Assche095c9442022-03-02 17:36:34 +0000592void BatteryMonitor::logValues(const HealthInfo_2_1& health_info,
593 const struct healthd_config& healthd_config) {
594 HealthInfo aidl_health_info;
595 (void)android::h2a::translate(health_info, &aidl_health_info);
596 doLogValues(aidl_health_info, healthd_config);
597}
598
599void BatteryMonitor::logValues(void) {
600 doLogValues(*mHealthInfo, *mHealthdConfig);
601}
602
Yifan Hong1353e702019-10-07 10:41:30 -0700603bool BatteryMonitor::isChargerOnline() {
Yifan Hongb99d15c2022-03-01 12:12:34 -0800604 const HealthInfo& props = *mHealthInfo;
Jack Wu06b90412021-12-15 20:40:21 +0800605 return props.chargerAcOnline | props.chargerUsbOnline | props.chargerWirelessOnline |
Yifan Hongb99d15c2022-03-01 12:12:34 -0800606 props.chargerDockOnline;
Todd Poynor752faf22013-06-12 13:25:59 -0700607}
608
Yabin Cuiaedf6032016-02-19 18:03:23 -0800609int BatteryMonitor::getChargeStatus() {
Yifan Hong1d4368b2019-10-07 11:18:04 -0700610 BatteryStatus result = BatteryStatus::UNKNOWN;
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000611 if (!mHealthdConfig->batteryStatusPath.empty()) {
Michael Scott3217c5c2016-06-05 11:20:13 -0700612 std::string buf;
613 if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
614 result = getBatteryStatus(buf.c_str());
Yabin Cuiaedf6032016-02-19 18:03:23 -0800615 }
Yifan Hong1d4368b2019-10-07 11:18:04 -0700616 return static_cast<int>(result);
Yabin Cuiaedf6032016-02-19 18:03:23 -0800617}
618
Jack Wue561d032022-11-24 12:19:41 +0800619status_t BatteryMonitor::setChargingPolicy(int value) {
620 status_t ret = NAME_NOT_FOUND;
621 bool result;
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000622 if (!mHealthdConfig->chargingPolicyPath.empty()) {
Jack Wue561d032022-11-24 12:19:41 +0800623 result = writeToFile(mHealthdConfig->chargingPolicyPath, value);
624 if (!result) {
625 KLOG_WARNING(LOG_TAG, "setChargingPolicy fail\n");
626 ret = BAD_VALUE;
627 } else {
628 ret = OK;
629 }
630 }
631 return ret;
632}
633
634int BatteryMonitor::getChargingPolicy() {
635 BatteryChargingPolicy result = BatteryChargingPolicy::DEFAULT;
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000636 if (!mHealthdConfig->chargingPolicyPath.empty()) {
Jack Wue561d032022-11-24 12:19:41 +0800637 std::string buf;
638 if (readFromFile(mHealthdConfig->chargingPolicyPath, &buf) > 0)
639 result = getBatteryChargingPolicy(buf.c_str());
640 }
641 return static_cast<int>(result);
642}
643
644int BatteryMonitor::getBatteryHealthData(int id) {
645 if (id == BATTERY_PROP_MANUFACTURING_DATE) {
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000646 if (!mHealthdConfig->batteryManufacturingDatePath.empty())
Jack Wue561d032022-11-24 12:19:41 +0800647 return getIntField(mHealthdConfig->batteryManufacturingDatePath);
648 }
649 if (id == BATTERY_PROP_FIRST_USAGE_DATE) {
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000650 if (!mHealthdConfig->batteryFirstUsageDatePath.empty())
Jack Wue561d032022-11-24 12:19:41 +0800651 return getIntField(mHealthdConfig->batteryFirstUsageDatePath);
652 }
AleX Pelosiff708922023-02-17 01:39:21 +0000653 if (id == BATTERY_PROP_STATE_OF_HEALTH) {
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000654 if (!mHealthdConfig->batteryStateOfHealthPath.empty())
AleX Pelosiff708922023-02-17 01:39:21 +0000655 return getIntField(mHealthdConfig->batteryStateOfHealthPath);
656 }
David Andersond5ed26a2023-12-08 15:12:24 -0800657 if (id == BATTERY_PROP_PART_STATUS) {
658 return static_cast<int>(BatteryPartStatus::UNSUPPORTED);
659 }
Jack Wue561d032022-11-24 12:19:41 +0800660 return 0;
661}
662
Todd Poynorc133b712013-08-14 17:39:13 -0700663status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
664 status_t ret = BAD_VALUE;
Jin Qian72adf112017-02-02 17:31:13 -0800665 std::string buf;
Todd Poynorc133b712013-08-14 17:39:13 -0700666
Todd Poynor8f132af2014-05-08 17:15:45 -0700667 val->valueInt64 = LONG_MIN;
668
Todd Poynorc133b712013-08-14 17:39:13 -0700669 switch(id) {
670 case BATTERY_PROP_CHARGE_COUNTER:
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000671 if (!mHealthdConfig->batteryChargeCounterPath.empty()) {
Todd Poynor8f132af2014-05-08 17:15:45 -0700672 val->valueInt64 =
Todd Poynorc133b712013-08-14 17:39:13 -0700673 getIntField(mHealthdConfig->batteryChargeCounterPath);
Elliott Hughes643268f2018-10-08 11:10:11 -0700674 ret = OK;
Todd Poynorc133b712013-08-14 17:39:13 -0700675 } else {
676 ret = NAME_NOT_FOUND;
677 }
678 break;
679
680 case BATTERY_PROP_CURRENT_NOW:
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000681 if (!mHealthdConfig->batteryCurrentNowPath.empty()) {
Todd Poynor8f132af2014-05-08 17:15:45 -0700682 val->valueInt64 =
Todd Poynorc133b712013-08-14 17:39:13 -0700683 getIntField(mHealthdConfig->batteryCurrentNowPath);
Elliott Hughes643268f2018-10-08 11:10:11 -0700684 ret = OK;
Todd Poynorc133b712013-08-14 17:39:13 -0700685 } else {
686 ret = NAME_NOT_FOUND;
687 }
688 break;
689
Todd Poynorbc102112013-08-27 18:11:49 -0700690 case BATTERY_PROP_CURRENT_AVG:
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000691 if (!mHealthdConfig->batteryCurrentAvgPath.empty()) {
Todd Poynor8f132af2014-05-08 17:15:45 -0700692 val->valueInt64 =
Todd Poynorbc102112013-08-27 18:11:49 -0700693 getIntField(mHealthdConfig->batteryCurrentAvgPath);
Elliott Hughes643268f2018-10-08 11:10:11 -0700694 ret = OK;
Todd Poynorbc102112013-08-27 18:11:49 -0700695 } else {
696 ret = NAME_NOT_FOUND;
697 }
698 break;
699
Paul Lawrence347c8de2014-03-19 15:04:40 -0700700 case BATTERY_PROP_CAPACITY:
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000701 if (!mHealthdConfig->batteryCapacityPath.empty()) {
Todd Poynor8f132af2014-05-08 17:15:45 -0700702 val->valueInt64 =
Paul Lawrence347c8de2014-03-19 15:04:40 -0700703 getIntField(mHealthdConfig->batteryCapacityPath);
Elliott Hughes643268f2018-10-08 11:10:11 -0700704 ret = OK;
Paul Lawrence347c8de2014-03-19 15:04:40 -0700705 } else {
706 ret = NAME_NOT_FOUND;
707 }
708 break;
709
Todd Poynor8f132af2014-05-08 17:15:45 -0700710 case BATTERY_PROP_ENERGY_COUNTER:
Todd Poynore14b37e2014-05-20 13:54:40 -0700711 if (mHealthdConfig->energyCounter) {
712 ret = mHealthdConfig->energyCounter(&val->valueInt64);
713 } else {
714 ret = NAME_NOT_FOUND;
715 }
Todd Poynor8f132af2014-05-08 17:15:45 -0700716 break;
717
Jin Qian72adf112017-02-02 17:31:13 -0800718 case BATTERY_PROP_BATTERY_STATUS:
Todd Poynore030a102018-01-19 14:03:59 -0800719 val->valueInt64 = getChargeStatus();
Elliott Hughes643268f2018-10-08 11:10:11 -0700720 ret = OK;
Jin Qian72adf112017-02-02 17:31:13 -0800721 break;
722
Jack Wue561d032022-11-24 12:19:41 +0800723 case BATTERY_PROP_CHARGING_POLICY:
724 val->valueInt64 = getChargingPolicy();
725 ret = OK;
726 break;
727
728 case BATTERY_PROP_MANUFACTURING_DATE:
729 val->valueInt64 = getBatteryHealthData(BATTERY_PROP_MANUFACTURING_DATE);
730 ret = OK;
731 break;
732
733 case BATTERY_PROP_FIRST_USAGE_DATE:
734 val->valueInt64 = getBatteryHealthData(BATTERY_PROP_FIRST_USAGE_DATE);
735 ret = OK;
736 break;
737
AleX Pelosiff708922023-02-17 01:39:21 +0000738 case BATTERY_PROP_STATE_OF_HEALTH:
739 val->valueInt64 = getBatteryHealthData(BATTERY_PROP_STATE_OF_HEALTH);
740 ret = OK;
741 break;
742
David Andersond5ed26a2023-12-08 15:12:24 -0800743 case BATTERY_PROP_PART_STATUS:
744 val->valueInt64 = getBatteryHealthData(BATTERY_PROP_PART_STATUS);
745 ret = OK;
746 break;
747
Todd Poynorc133b712013-08-14 17:39:13 -0700748 default:
749 break;
750 }
751
Todd Poynorc133b712013-08-14 17:39:13 -0700752 return ret;
753}
754
David Andersond5ed26a2023-12-08 15:12:24 -0800755status_t BatteryMonitor::getSerialNumber(std::optional<std::string>* out) {
756 *out = std::nullopt;
757 return OK;
758}
759
Todd Poynor020369d2013-09-18 20:09:33 -0700760void BatteryMonitor::dumpState(int fd) {
761 int v;
762 char vs[128];
Yifan Hongb99d15c2022-03-01 12:12:34 -0800763 const HealthInfo& props = *mHealthInfo;
Todd Poynor020369d2013-09-18 20:09:33 -0700764
YiKai Pengae455db2025-03-10 23:41:17 -0700765 snprintf(vs, sizeof(vs), "Cached HealthInfo:\n");
766 write(fd, vs, strlen(vs));
Jack Wu06b90412021-12-15 20:40:21 +0800767 snprintf(vs, sizeof(vs),
YiKai Pengae455db2025-03-10 23:41:17 -0700768 " ac: %d usb: %d wireless: %d dock: %d current_max: %d voltage_max: %d\n",
Jack Wu06b90412021-12-15 20:40:21 +0800769 props.chargerAcOnline, props.chargerUsbOnline, props.chargerWirelessOnline,
Yifan Hongb99d15c2022-03-01 12:12:34 -0800770 props.chargerDockOnline, props.maxChargingCurrentMicroamps,
771 props.maxChargingVoltageMicrovolts);
Todd Poynor020369d2013-09-18 20:09:33 -0700772 write(fd, vs, strlen(vs));
YiKai Pengae455db2025-03-10 23:41:17 -0700773 snprintf(vs, sizeof(vs), " status: %d health: %d present: %d\n",
Todd Poynor020369d2013-09-18 20:09:33 -0700774 props.batteryStatus, props.batteryHealth, props.batteryPresent);
775 write(fd, vs, strlen(vs));
YiKai Pengae455db2025-03-10 23:41:17 -0700776 snprintf(vs, sizeof(vs), " level: %d voltage: %d temp: %d\n", props.batteryLevel,
Yifan Hongb99d15c2022-03-01 12:12:34 -0800777 props.batteryVoltageMillivolts, props.batteryTemperatureTenthsCelsius);
Todd Poynor020369d2013-09-18 20:09:33 -0700778 write(fd, vs, strlen(vs));
779
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000780 if (!mHealthdConfig->batteryCurrentNowPath.empty()) {
YiKai Pengae455db2025-03-10 23:41:17 -0700781 snprintf(vs, sizeof(vs), " current now: %d\n", props.batteryCurrentMicroamps);
782 write(fd, vs, strlen(vs));
783 }
784
785 if (!mHealthdConfig->batteryCycleCountPath.empty()) {
786 snprintf(vs, sizeof(vs), " cycle count: %d\n", props.batteryCycleCount);
787 write(fd, vs, strlen(vs));
788 }
789
790 if (!mHealthdConfig->batteryFullChargePath.empty()) {
791 snprintf(vs, sizeof(vs), " Full charge: %d\n", props.batteryFullChargeUah);
792 write(fd, vs, strlen(vs));
793 }
794
795 snprintf(vs, sizeof(vs), "Real-time Values:\n");
796 write(fd, vs, strlen(vs));
797
798 if (!mHealthdConfig->batteryCurrentNowPath.empty()) {
Todd Poynor020369d2013-09-18 20:09:33 -0700799 v = getIntField(mHealthdConfig->batteryCurrentNowPath);
YiKai Pengae455db2025-03-10 23:41:17 -0700800 snprintf(vs, sizeof(vs), " current now: %d\n", v);
Todd Poynor020369d2013-09-18 20:09:33 -0700801 write(fd, vs, strlen(vs));
802 }
803
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000804 if (!mHealthdConfig->batteryCurrentAvgPath.empty()) {
Todd Poynor020369d2013-09-18 20:09:33 -0700805 v = getIntField(mHealthdConfig->batteryCurrentAvgPath);
YiKai Pengae455db2025-03-10 23:41:17 -0700806 snprintf(vs, sizeof(vs), " current avg: %d\n", v);
Todd Poynor020369d2013-09-18 20:09:33 -0700807 write(fd, vs, strlen(vs));
808 }
809
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000810 if (!mHealthdConfig->batteryChargeCounterPath.empty()) {
Todd Poynor020369d2013-09-18 20:09:33 -0700811 v = getIntField(mHealthdConfig->batteryChargeCounterPath);
YiKai Pengae455db2025-03-10 23:41:17 -0700812 snprintf(vs, sizeof(vs), " charge counter: %d\n", v);
Ruchi Kandoicc338802015-08-24 13:01:16 -0700813 write(fd, vs, strlen(vs));
814 }
Todd Poynor020369d2013-09-18 20:09:33 -0700815}
816
Todd Poynorc7464c92013-09-10 12:40:00 -0700817void BatteryMonitor::init(struct healthd_config *hc) {
Todd Poynor752faf22013-06-12 13:25:59 -0700818 String8 path;
Todd Poynor3db03a52014-05-21 16:28:13 -0700819 char pval[PROPERTY_VALUE_MAX];
Todd Poynor752faf22013-06-12 13:25:59 -0700820
Todd Poynorf5d30122013-08-12 17:03:35 -0700821 mHealthdConfig = hc;
James Hawkins588a2ca2016-02-18 14:52:46 -0800822 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir);
Todd Poynor752faf22013-06-12 13:25:59 -0700823 if (dir == NULL) {
824 KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
825 } else {
826 struct dirent* entry;
827
James Hawkins588a2ca2016-02-18 14:52:46 -0800828 while ((entry = readdir(dir.get()))) {
Todd Poynor752faf22013-06-12 13:25:59 -0700829 const char* name = entry->d_name;
830
831 if (!strcmp(name, ".") || !strcmp(name, ".."))
832 continue;
833
Bart Van Assche25b2a8d2022-02-24 21:51:34 +0000834 std::vector<String8>::iterator itIgnoreName =
835 find(hc->ignorePowerSupplyNames.begin(), hc->ignorePowerSupplyNames.end(),
836 String8(name));
Thierry Strudelf73de6f2019-01-11 17:09:20 -0800837 if (itIgnoreName != hc->ignorePowerSupplyNames.end())
838 continue;
839
Todd Poynor752faf22013-06-12 13:25:59 -0700840 // Look for "type" file in each subdirectory
841 path.clear();
842 path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
843 switch(readPowerSupplyType(path)) {
844 case ANDROID_POWER_SUPPLY_TYPE_AC:
845 case ANDROID_POWER_SUPPLY_TYPE_USB:
846 case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
Jack Wu06b90412021-12-15 20:40:21 +0800847 case ANDROID_POWER_SUPPLY_TYPE_DOCK:
Todd Poynor752faf22013-06-12 13:25:59 -0700848 path.clear();
849 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk18b74612023-08-10 23:29:50 +0000850 if (access(path.c_str(), R_OK) == 0) mChargerNames.add(String8(name));
Todd Poynor752faf22013-06-12 13:25:59 -0700851 break;
852
853 case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
Kazuhiro Inaba8e4d9822019-06-12 13:46:08 +0900854 // Some devices expose the battery status of sub-component like
855 // stylus. Such a device-scoped battery info needs to be skipped
856 // in BatteryMonitor, which is intended to report the status of
857 // the battery supplying the power to the whole system.
858 if (isScopedPowerSupply(name)) continue;
Todd Poynor6dcc45e2013-10-21 20:26:25 -0700859 mBatteryDevicePresent = true;
860
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000861 if (mHealthdConfig->batteryStatusPath.empty()) {
Todd Poynor752faf22013-06-12 13:25:59 -0700862 path.clear();
Todd Poynorf5d30122013-08-12 17:03:35 -0700863 path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
864 name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000865 if (access(path.c_str(), R_OK) == 0) mHealthdConfig->batteryStatusPath = path;
Todd Poynor752faf22013-06-12 13:25:59 -0700866 }
867
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000868 if (mHealthdConfig->batteryHealthPath.empty()) {
Todd Poynor752faf22013-06-12 13:25:59 -0700869 path.clear();
Todd Poynorf5d30122013-08-12 17:03:35 -0700870 path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
871 name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000872 if (access(path.c_str(), R_OK) == 0) mHealthdConfig->batteryHealthPath = path;
Todd Poynor752faf22013-06-12 13:25:59 -0700873 }
874
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000875 if (mHealthdConfig->batteryPresentPath.empty()) {
Todd Poynorf5d30122013-08-12 17:03:35 -0700876 path.clear();
877 path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
878 name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000879 if (access(path.c_str(), R_OK) == 0) mHealthdConfig->batteryPresentPath = path;
Todd Poynorf5d30122013-08-12 17:03:35 -0700880 }
881
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000882 if (mHealthdConfig->batteryCapacityPath.empty()) {
Todd Poynorf5d30122013-08-12 17:03:35 -0700883 path.clear();
884 path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
885 name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000886 if (access(path.c_str(), R_OK) == 0) mHealthdConfig->batteryCapacityPath = path;
Todd Poynorf5d30122013-08-12 17:03:35 -0700887 }
888
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000889 if (mHealthdConfig->batteryVoltagePath.empty()) {
Todd Poynorf5d30122013-08-12 17:03:35 -0700890 path.clear();
891 path.appendFormat("%s/%s/voltage_now",
892 POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000893 if (access(path.c_str(), R_OK) == 0) {
Todd Poynorf5d30122013-08-12 17:03:35 -0700894 mHealthdConfig->batteryVoltagePath = path;
Todd Poynorf5d30122013-08-12 17:03:35 -0700895 }
896 }
897
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000898 if (mHealthdConfig->batteryFullChargePath.empty()) {
Ruchi Kandoicc338802015-08-24 13:01:16 -0700899 path.clear();
900 path.appendFormat("%s/%s/charge_full",
901 POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000902 if (access(path.c_str(), R_OK) == 0)
Ruchi Kandoicc338802015-08-24 13:01:16 -0700903 mHealthdConfig->batteryFullChargePath = path;
904 }
905
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000906 if (mHealthdConfig->batteryCurrentNowPath.empty()) {
Todd Poynorf5d30122013-08-12 17:03:35 -0700907 path.clear();
908 path.appendFormat("%s/%s/current_now",
909 POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000910 if (access(path.c_str(), R_OK) == 0)
Todd Poynorf5d30122013-08-12 17:03:35 -0700911 mHealthdConfig->batteryCurrentNowPath = path;
912 }
913
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000914 if (mHealthdConfig->batteryCycleCountPath.empty()) {
Ruchi Kandoicc338802015-08-24 13:01:16 -0700915 path.clear();
916 path.appendFormat("%s/%s/cycle_count",
917 POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000918 if (access(path.c_str(), R_OK) == 0)
Ruchi Kandoicc338802015-08-24 13:01:16 -0700919 mHealthdConfig->batteryCycleCountPath = path;
920 }
921
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000922 if (mHealthdConfig->batteryCapacityLevelPath.empty()) {
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800923 path.clear();
924 path.appendFormat("%s/%s/capacity_level", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000925 if (access(path.c_str(), R_OK) == 0) {
926 mHealthdConfig->batteryCapacityLevelPath = path;
927 }
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800928 }
929
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000930 if (mHealthdConfig->batteryChargeTimeToFullNowPath.empty()) {
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800931 path.clear();
932 path.appendFormat("%s/%s/time_to_full_now", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000933 if (access(path.c_str(), R_OK) == 0)
Stephane Lee86f9f6a2019-12-19 15:09:41 -0800934 mHealthdConfig->batteryChargeTimeToFullNowPath = path;
935 }
936
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000937 if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.empty()) {
Stephane Lee1c108ed2020-02-10 18:23:57 -0800938 path.clear();
939 path.appendFormat("%s/%s/charge_full_design", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000940 if (access(path.c_str(), R_OK) == 0)
Stephane Lee1c108ed2020-02-10 18:23:57 -0800941 mHealthdConfig->batteryFullChargeDesignCapacityUahPath = path;
942 }
943
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000944 if (mHealthdConfig->batteryCurrentAvgPath.empty()) {
Todd Poynorbc102112013-08-27 18:11:49 -0700945 path.clear();
946 path.appendFormat("%s/%s/current_avg",
947 POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000948 if (access(path.c_str(), R_OK) == 0)
Todd Poynorbc102112013-08-27 18:11:49 -0700949 mHealthdConfig->batteryCurrentAvgPath = path;
950 }
951
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000952 if (mHealthdConfig->batteryChargeCounterPath.empty()) {
Todd Poynorf5d30122013-08-12 17:03:35 -0700953 path.clear();
954 path.appendFormat("%s/%s/charge_counter",
955 POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000956 if (access(path.c_str(), R_OK) == 0)
Todd Poynorf5d30122013-08-12 17:03:35 -0700957 mHealthdConfig->batteryChargeCounterPath = path;
958 }
959
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000960 if (mHealthdConfig->batteryTemperaturePath.empty()) {
Todd Poynorf5d30122013-08-12 17:03:35 -0700961 path.clear();
962 path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
963 name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000964 if (access(path.c_str(), R_OK) == 0) {
Todd Poynorf5d30122013-08-12 17:03:35 -0700965 mHealthdConfig->batteryTemperaturePath = path;
Todd Poynorf5d30122013-08-12 17:03:35 -0700966 }
967 }
968
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000969 if (mHealthdConfig->batteryTechnologyPath.empty()) {
Todd Poynorf5d30122013-08-12 17:03:35 -0700970 path.clear();
971 path.appendFormat("%s/%s/technology",
972 POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000973 if (access(path.c_str(), R_OK) == 0)
Todd Poynorf5d30122013-08-12 17:03:35 -0700974 mHealthdConfig->batteryTechnologyPath = path;
975 }
976
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000977 if (mHealthdConfig->batteryStateOfHealthPath.empty()) {
Jack Wue561d032022-11-24 12:19:41 +0800978 path.clear();
979 path.appendFormat("%s/%s/state_of_health", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000980 if (access(path.c_str(), R_OK) == 0) {
Jack Wue561d032022-11-24 12:19:41 +0800981 mHealthdConfig->batteryStateOfHealthPath = path;
982 } else {
983 path.clear();
984 path.appendFormat("%s/%s/health_index", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000985 if (access(path.c_str(), R_OK) == 0)
Jack Wue561d032022-11-24 12:19:41 +0800986 mHealthdConfig->batteryStateOfHealthPath = path;
987 }
988 }
989
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000990 if (mHealthdConfig->batteryHealthStatusPath.empty()) {
Jack Wub57f68a2023-02-04 19:56:06 +0800991 path.clear();
992 path.appendFormat("%s/%s/health_status", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +0000993 if (access(path.c_str(), R_OK) == 0) {
994 mHealthdConfig->batteryHealthStatusPath = path;
995 }
Jack Wub57f68a2023-02-04 19:56:06 +0800996 }
997
Tomasz Wasilczykf5971292023-08-14 18:18:26 +0000998 if (mHealthdConfig->batteryManufacturingDatePath.empty()) {
Jack Wue561d032022-11-24 12:19:41 +0800999 path.clear();
1000 path.appendFormat("%s/%s/manufacturing_date", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +00001001 if (access(path.c_str(), R_OK) == 0)
Jack Wue561d032022-11-24 12:19:41 +08001002 mHealthdConfig->batteryManufacturingDatePath = path;
1003 }
1004
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001005 if (mHealthdConfig->batteryFirstUsageDatePath.empty()) {
Jack Wue561d032022-11-24 12:19:41 +08001006 path.clear();
1007 path.appendFormat("%s/%s/first_usage_date", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +00001008 if (access(path.c_str(), R_OK) == 0) {
1009 mHealthdConfig->batteryFirstUsageDatePath = path;
1010 }
Jack Wue561d032022-11-24 12:19:41 +08001011 }
1012
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001013 if (mHealthdConfig->chargingStatePath.empty()) {
Jack Wue561d032022-11-24 12:19:41 +08001014 path.clear();
1015 path.appendFormat("%s/%s/charging_state", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +00001016 if (access(path.c_str(), R_OK) == 0) mHealthdConfig->chargingStatePath = path;
Jack Wue561d032022-11-24 12:19:41 +08001017 }
1018
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001019 if (mHealthdConfig->chargingPolicyPath.empty()) {
Jack Wue561d032022-11-24 12:19:41 +08001020 path.clear();
1021 path.appendFormat("%s/%s/charging_policy", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk2b1a0592023-09-12 15:26:15 +00001022 if (access(path.c_str(), R_OK) == 0) mHealthdConfig->chargingPolicyPath = path;
Jack Wue561d032022-11-24 12:19:41 +08001023 }
1024
Todd Poynor752faf22013-06-12 13:25:59 -07001025 break;
1026
1027 case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
1028 break;
1029 }
Jack Wu06b90412021-12-15 20:40:21 +08001030
1031 // Look for "is_dock" file
1032 path.clear();
1033 path.appendFormat("%s/%s/is_dock", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk18b74612023-08-10 23:29:50 +00001034 if (access(path.c_str(), R_OK) == 0) {
Jack Wu06b90412021-12-15 20:40:21 +08001035 path.clear();
1036 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
Tomasz Wasilczyk18b74612023-08-10 23:29:50 +00001037 if (access(path.c_str(), R_OK) == 0) mChargerNames.add(String8(name));
Jack Wu06b90412021-12-15 20:40:21 +08001038 }
Todd Poynor752faf22013-06-12 13:25:59 -07001039 }
Todd Poynor752faf22013-06-12 13:25:59 -07001040 }
1041
Ian Pedowitz585ab652015-10-12 19:01:00 -07001042 // Typically the case for devices which do not have a battery and
1043 // and are always plugged into AC mains.
Todd Poynor6dcc45e2013-10-21 20:26:25 -07001044 if (!mBatteryDevicePresent) {
Todd Poynorebeb0c02014-09-23 14:54:24 -07001045 KLOG_WARNING(LOG_TAG, "No battery devices found\n");
Todd Poynor6dcc45e2013-10-21 20:26:25 -07001046 hc->periodic_chores_interval_fast = -1;
1047 hc->periodic_chores_interval_slow = -1;
1048 } else {
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001049 if (mHealthdConfig->batteryStatusPath.empty())
Todd Poynor6dcc45e2013-10-21 20:26:25 -07001050 KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001051 if (mHealthdConfig->batteryHealthPath.empty())
Todd Poynor6dcc45e2013-10-21 20:26:25 -07001052 KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001053 if (mHealthdConfig->batteryPresentPath.empty())
Todd Poynor6dcc45e2013-10-21 20:26:25 -07001054 KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001055 if (mHealthdConfig->batteryCapacityPath.empty())
Todd Poynor6dcc45e2013-10-21 20:26:25 -07001056 KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001057 if (mHealthdConfig->batteryVoltagePath.empty())
Todd Poynor6dcc45e2013-10-21 20:26:25 -07001058 KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001059 if (mHealthdConfig->batteryTemperaturePath.empty())
Todd Poynor6dcc45e2013-10-21 20:26:25 -07001060 KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001061 if (mHealthdConfig->batteryTechnologyPath.empty())
Todd Poynor6dcc45e2013-10-21 20:26:25 -07001062 KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001063 if (mHealthdConfig->batteryCurrentNowPath.empty())
Ruchi Kandoicc338802015-08-24 13:01:16 -07001064 KLOG_WARNING(LOG_TAG, "BatteryCurrentNowPath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001065 if (mHealthdConfig->batteryFullChargePath.empty())
Ruchi Kandoicc338802015-08-24 13:01:16 -07001066 KLOG_WARNING(LOG_TAG, "BatteryFullChargePath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001067 if (mHealthdConfig->batteryCycleCountPath.empty())
Ruchi Kandoicc338802015-08-24 13:01:16 -07001068 KLOG_WARNING(LOG_TAG, "BatteryCycleCountPath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001069 if (mHealthdConfig->batteryCapacityLevelPath.empty())
Stephane Lee86f9f6a2019-12-19 15:09:41 -08001070 KLOG_WARNING(LOG_TAG, "batteryCapacityLevelPath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001071 if (mHealthdConfig->batteryChargeTimeToFullNowPath.empty())
Stephane Lee86f9f6a2019-12-19 15:09:41 -08001072 KLOG_WARNING(LOG_TAG, "batteryChargeTimeToFullNowPath. not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001073 if (mHealthdConfig->batteryFullChargeDesignCapacityUahPath.empty())
Stephane Lee1c108ed2020-02-10 18:23:57 -08001074 KLOG_WARNING(LOG_TAG, "batteryFullChargeDesignCapacityUahPath. not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001075 if (mHealthdConfig->batteryStateOfHealthPath.empty())
Jack Wue561d032022-11-24 12:19:41 +08001076 KLOG_WARNING(LOG_TAG, "batteryStateOfHealthPath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001077 if (mHealthdConfig->batteryHealthStatusPath.empty())
Jack Wub57f68a2023-02-04 19:56:06 +08001078 KLOG_WARNING(LOG_TAG, "batteryHealthStatusPath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001079 if (mHealthdConfig->batteryManufacturingDatePath.empty())
Jack Wue561d032022-11-24 12:19:41 +08001080 KLOG_WARNING(LOG_TAG, "batteryManufacturingDatePath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001081 if (mHealthdConfig->batteryFirstUsageDatePath.empty())
Jack Wue561d032022-11-24 12:19:41 +08001082 KLOG_WARNING(LOG_TAG, "batteryFirstUsageDatePath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001083 if (mHealthdConfig->chargingStatePath.empty())
Jack Wue561d032022-11-24 12:19:41 +08001084 KLOG_WARNING(LOG_TAG, "chargingStatePath not found\n");
Tomasz Wasilczykf5971292023-08-14 18:18:26 +00001085 if (mHealthdConfig->chargingPolicyPath.empty())
Jack Wue561d032022-11-24 12:19:41 +08001086 KLOG_WARNING(LOG_TAG, "chargingPolicyPath not found\n");
Todd Poynor6dcc45e2013-10-21 20:26:25 -07001087 }
Todd Poynor3db03a52014-05-21 16:28:13 -07001088
Ruchi Kandoia78fc232014-07-10 15:06:21 -07001089 if (property_get("ro.boot.fake_battery", pval, NULL) > 0
1090 && strtol(pval, NULL, 10) != 0) {
1091 mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY;
1092 mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
1093 }
Todd Poynor752faf22013-06-12 13:25:59 -07001094}
1095
1096}; // namespace android