1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "power_supply_provider.h"
17 #include <dirent.h>
18 #include <fcntl.h>
19 #include <fstream>
20 #include <securec.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include "battery_log.h"
25 #include "battery_config.h"
26 #include "osal_mem.h"
27
28 namespace OHOS {
29 namespace HDI {
30 namespace Battery {
31 namespace V1_2 {
32 namespace {
33 constexpr int32_t MAX_SYSFS_SIZE = 64;
34 constexpr int32_t MAX_BUFF_SIZE = 128;
35 constexpr int32_t INVALID_BATT_INT_VALUE = -1;
36 constexpr int32_t STR_TO_LONG_LEN = 10;
37 constexpr int32_t UVOL_TO_MVOL = 1000;
38 constexpr int32_t MKDIR_WAIT_TIME = 1;
39 constexpr int32_t NUM_ZERO = 0;
40 const std::string POWER_SUPPLY_BASE_PATH = "/sys/class/power_supply";
41 const std::string MOCK_POWER_SUPPLY_BASE_PATH = "/data/service/el0/battery";
42 const std::string POWER_SUPPLY_BATTERY = "Battery";
43 const std::string BATTERY_KEY_CAPACITY = "POWER_SUPPLY_CAPACITY=";
44 const std::string BATTERY_KEY_VOLTAGE = "POWER_SUPPLY_VOLTAGE_NOW=";
45 const std::string BATTERY_KEY_TEMPERATURE = "POWER_SUPPLY_TEMP=";
46 const std::string BATTERY_KEY_HEALTH = "POWER_SUPPLY_HEALTH=";
47 const std::string BATTERY_KEY_CHARGE_STATUS = "POWER_SUPPLY_STATUS=";
48 const std::string BATTERY_KEY_PRESENT = "POWER_SUPPLY_PRESENT=";
49 const std::string BATTERY_KEY_TECHNOLOGY = "POWER_SUPPLY_TECHNOLOGY=";
50 const std::string BATTERY_KEY_CHARGE_COUNTER = "POWER_SUPPLY_CHARGE_COUNTER=";
51 const std::string BATTERY_KEY_TOTAL_ENERGY = "POWER_SUPPLY_TOTAL_ENERGY=";
52 const std::string BATTERY_KEY_REMAIN_ENERGY = "POWER_SUPPLY_REMAIN_ENERGY=";
53 const std::string BATTERY_KEY_CURRENT_AVERAGE = "POWER_SUPPLY_CURRENT_AVERAGE=";
54 const std::string BATTERY_KEY_CURRENT_NOW = "POWER_SUPPLY_CURRENT_NOW=";
55 const std::string INVALID_STRING_VALUE = "invalid";
56 const std::string BATTERY_NODE_PATH = "battery";
57 }
58
59 BatterydInfo g_batteryInfo;
60
61 struct StringEnumMap {
62 const char* str;
63 int32_t enumVal;
64 };
65
66 struct BatteryAssigner {
67 const char* prefix;
68 const size_t prefixLen;
69 void (*Assigner)(const char*, struct BatterydInfo*);
70 };
71
PowerSupplyProvider()72 PowerSupplyProvider::PowerSupplyProvider()
73 {
74 path_ = POWER_SUPPLY_BASE_PATH;
75 index_ = 0;
76 }
77
ParseInt(const char * str)78 inline int32_t PowerSupplyProvider::ParseInt(const char* str)
79 {
80 return static_cast<int32_t>(strtol(str, nullptr, STR_TO_LONG_LEN));
81 }
82
Trim(char * str)83 inline void PowerSupplyProvider::Trim(char* str)
84 {
85 if (str == nullptr) {
86 return;
87 }
88
89 str[strcspn(str, "\n")] = 0;
90 }
91
CapacityAssigner(const char * str,struct BatterydInfo * info)92 inline void PowerSupplyProvider::CapacityAssigner(const char* str, struct BatterydInfo* info)
93 {
94 info->capacity_ = ParseInt(str); // default in percent format
95 }
96
TotalEnergyAssigner(const char * str,struct BatterydInfo * info)97 inline void PowerSupplyProvider::TotalEnergyAssigner(const char* str, struct BatterydInfo* info)
98 {
99 info->totalEnergy_ = ParseInt(str);
100 }
101
RemainEnergyAssigner(const char * str,struct BatterydInfo * info)102 inline void PowerSupplyProvider::RemainEnergyAssigner(const char* str, struct BatterydInfo* info)
103 {
104 info->remainEnergy_ = ParseInt(str);
105 }
106
VoltageAssigner(const char * str,struct BatterydInfo * info)107 inline void PowerSupplyProvider::VoltageAssigner(const char* str, struct BatterydInfo* info)
108 {
109 info->voltage_ = ParseInt(str) / UVOL_TO_MVOL; // convert to millivolt(mV) format
110 }
111
TemperatureAssigner(const char * str,struct BatterydInfo * info)112 inline void PowerSupplyProvider::TemperatureAssigner(const char* str, struct BatterydInfo* info)
113 {
114 info->temperature_ = ParseInt(str);
115 }
116
HealthStateEnumConverter(const char * str)117 int32_t PowerSupplyProvider::HealthStateEnumConverter(const char* str)
118 {
119 struct StringEnumMap healthStateEnumMap[] = {
120 { "Good", BATTERY_HEALTH_GOOD },
121 { "Cold", BATTERY_HEALTH_COLD },
122 { "Warm", BATTERY_HEALTH_GOOD }, // JEITA specification
123 { "Cool", BATTERY_HEALTH_GOOD }, // JEITA specification
124 { "Hot", BATTERY_HEALTH_OVERHEAT }, // JEITA specification
125 { "Overheat", BATTERY_HEALTH_OVERHEAT },
126 { "Over voltage", BATTERY_HEALTH_OVERVOLTAGE },
127 { "Dead", BATTERY_HEALTH_DEAD },
128 { "Unknown", BATTERY_HEALTH_UNKNOWN },
129 { "Unspecified failure", BATTERY_HEALTH_UNKNOWN },
130 { nullptr, BATTERY_HEALTH_UNKNOWN },
131 };
132
133 for (int32_t i = 0; healthStateEnumMap[i].str; ++i) {
134 if (strcmp(str, healthStateEnumMap[i].str) == 0) {
135 return healthStateEnumMap[i].enumVal;
136 }
137 }
138
139 return BATTERY_HEALTH_UNKNOWN;
140 }
141
HealthStateAssigner(const char * str,struct BatterydInfo * info)142 inline void PowerSupplyProvider::HealthStateAssigner(const char* str, struct BatterydInfo* info)
143 {
144 info->healthState_ = HealthStateEnumConverter(str);
145 }
146
ChargeStateEnumConverter(const char * str)147 int32_t PowerSupplyProvider::ChargeStateEnumConverter(const char* str)
148 {
149 struct StringEnumMap chargeStateEnumMap[] = {
150 { "Discharging", CHARGE_STATE_NONE },
151 { "Charging", CHARGE_STATE_ENABLE },
152 { "Full", CHARGE_STATE_FULL },
153 { "Not charging", CHARGE_STATE_DISABLE },
154 { "Unknown", CHARGE_STATE_RESERVED },
155 { nullptr, CHARGE_STATE_RESERVED },
156 };
157
158 for (int32_t i = 0; chargeStateEnumMap[i].str; ++i) {
159 if (strcmp(str, chargeStateEnumMap[i].str) == 0) {
160 return chargeStateEnumMap[i].enumVal;
161 }
162 }
163
164 return CHARGE_STATE_RESERVED;
165 }
166
ChargeTypeEumConverter(const char * str)167 int32_t PowerSupplyProvider::ChargeTypeEumConverter(const char* str)
168 {
169 struct StringEnumMap chargeTypeEnumMap[] = {
170 { "0", CHARGE_TYPE_NONE },
171 { "1", CHARGE_TYPE_WIRED_NORMAL },
172 { "2", CHARGE_TYPE_WIRED_QUICK },
173 { "3", CHARGE_TYPE_WIRED_SUPER_QUICK },
174 { "4", CHARGE_TYPE_WIRELESS_NORMAL },
175 { "5", CHARGE_TYPE_WIRELESS_QUICK },
176 { "6", CHARGE_TYPE_WIRELESS_SUPER_QUICK },
177 { nullptr, CHARGE_TYPE_NONE },
178 };
179
180 for (int32_t i = 0; chargeTypeEnumMap[i].str; ++i) {
181 if (strcmp(str, chargeTypeEnumMap[i].str) == 0) {
182 return chargeTypeEnumMap[i].enumVal;
183 }
184 }
185
186 return CHARGE_TYPE_NONE;
187 }
188
ChargeStateAssigner(const char * str,struct BatterydInfo * info)189 inline void PowerSupplyProvider::ChargeStateAssigner(const char* str, struct BatterydInfo* info)
190 {
191 info->chargeState_ = ChargeStateEnumConverter(str);
192 }
193
PresentAssigner(const char * str,struct BatterydInfo * info)194 inline void PowerSupplyProvider::PresentAssigner(const char* str, struct BatterydInfo* info)
195 {
196 info->present_ = static_cast<int8_t>(ParseInt(str));
197 }
198
TechnologyAssigner(const char * str,struct BatterydInfo * info)199 inline void PowerSupplyProvider::TechnologyAssigner(const char* str, struct BatterydInfo* info)
200 {
201 info->technology_ = str;
202 }
203
ChargeCounterAssigner(const char * str,struct BatterydInfo * info)204 inline void PowerSupplyProvider::ChargeCounterAssigner(const char* str, struct BatterydInfo* info)
205 {
206 info->chargeCounter_ = ParseInt(str);
207 }
208
CurrentAverageAssigner(const char * str,struct BatterydInfo * info)209 inline void PowerSupplyProvider::CurrentAverageAssigner(const char* str, struct BatterydInfo* info)
210 {
211 info->curAverage_ = ParseInt(str);
212 }
213
CurrentNowAssigner(const char * str,struct BatterydInfo * info)214 inline void PowerSupplyProvider::CurrentNowAssigner(const char* str, struct BatterydInfo* info)
215 {
216 info->curNow_ = ParseInt(str);
217 }
218
FormatPath(std::string & path,size_t size,const char * format,const char * basePath,const char * name) const219 void PowerSupplyProvider::FormatPath(std::string& path,
220 size_t size, const char* format, const char* basePath, const char* name) const
221 {
222 char buff[PATH_MAX] = {0};
223 if (strcpy_s(buff, PATH_MAX, path.c_str()) != EOK) {
224 BATTERY_HILOGW(FEATURE_BATT_INFO, "failed to copy path of %{public}s", name);
225 return;
226 }
227
228 if (snprintf_s(buff, PATH_MAX, size - 1, format, basePath, name) == -1) {
229 BATTERY_HILOGW(FEATURE_BATT_INFO, "failed to format path of %{public}s", name);
230 return;
231 }
232 path.assign(buff, strlen(buff));
233 }
234
FormatSysfsPaths()235 void PowerSupplyProvider::FormatSysfsPaths()
236 {
237 // Format paths for power supply types
238 FormatPath(batterySysfsInfo_.capacityPath, PATH_MAX, "%s/%s/capacity", path_.c_str(),
239 nodeNamePathMap_["capacity"].c_str());
240 FormatPath(batterySysfsInfo_.voltagePath, PATH_MAX, "%s/%s/voltage_now", path_.c_str(),
241 nodeNamePathMap_["voltage_now"].c_str());
242 FormatPath(batterySysfsInfo_.temperaturePath, PATH_MAX, "%s/%s/temp", path_.c_str(),
243 nodeNamePathMap_["temp"].c_str());
244 FormatPath(batterySysfsInfo_.healthStatePath, PATH_MAX, "%s/%s/health", path_.c_str(),
245 nodeNamePathMap_["health"].c_str());
246 FormatPath(batterySysfsInfo_.chargeStatePath, PATH_MAX, "%s/%s/status", path_.c_str(),
247 nodeNamePathMap_["status"].c_str());
248 FormatPath(batterySysfsInfo_.presentPath, PATH_MAX, "%s/%s/present", path_.c_str(),
249 nodeNamePathMap_["present"].c_str());
250 FormatPath(batterySysfsInfo_.chargeCounterPath, PATH_MAX, "%s/%s/charge_counter", path_.c_str(),
251 nodeNamePathMap_["charge_counter"].c_str());
252 FormatPath(batterySysfsInfo_.technologyPath, PATH_MAX, "%s/%s/technology", path_.c_str(),
253 nodeNamePathMap_["technology"].c_str());
254 FormatPath(batterySysfsInfo_.totalEnergyPath, PATH_MAX, "%s/%s/charge_full", path_.c_str(),
255 nodeNamePathMap_["charge_full"].c_str());
256 FormatPath(batterySysfsInfo_.curAveragePath, PATH_MAX, "%s/%s/current_avg", path_.c_str(),
257 nodeNamePathMap_["current_avg"].c_str());
258 FormatPath(batterySysfsInfo_.curNowPath, PATH_MAX, "%s/%s/current_now", path_.c_str(),
259 nodeNamePathMap_["current_now"].c_str());
260 FormatPath(batterySysfsInfo_.remainEnergyPath, PATH_MAX, "%s/%s/charge_now", path_.c_str(),
261 nodeNamePathMap_["charge_now"].c_str());
262 }
263
ReadSysfsFile(const char * path,char * buf,size_t size) const264 int32_t PowerSupplyProvider::ReadSysfsFile(const char* path, char* buf, size_t size) const
265 {
266 int32_t fd = open(path, O_RDONLY, S_IRUSR | S_IRGRP | S_IROTH);
267 if (fd < NUM_ZERO) {
268 BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to open file");
269 return HDF_ERR_IO;
270 }
271
272 size_t readSize = read(fd, buf, size - 1);
273 buf[readSize] = '\0';
274 Trim(buf);
275 close(fd);
276
277 return HDF_SUCCESS;
278 }
279
ReadBatterySysfsToBuff(const char * path,char * buf,size_t size) const280 int32_t PowerSupplyProvider::ReadBatterySysfsToBuff(const char* path, char* buf, size_t size) const
281 {
282 int32_t ret = ReadSysfsFile(path, buf, size);
283 if (ret != HDF_SUCCESS) {
284 BATTERY_HILOGW(FEATURE_BATT_INFO, "read path failed, ret: %{public}d", ret);
285 return ret;
286 }
287
288 return HDF_SUCCESS;
289 }
290
GetPluggedTypeName(char * buf,size_t size) const291 void PowerSupplyProvider::GetPluggedTypeName(char* buf, size_t size) const
292 {
293 std::string onlineNode = "USB";
294 int32_t ret;
295 int32_t online;
296 std::string onlinePath;
297
298 auto iter = nodeNames_.begin();
299 while (iter != nodeNames_.end()) {
300 onlinePath = path_ + "/" + *iter + "/" + "online";
301 ret = ReadSysfsFile(onlinePath.c_str(), buf, size);
302 if (ret != HDF_SUCCESS) {
303 BATTERY_HILOGW(FEATURE_BATT_INFO, "read online path failed in loop, ret: %{public}d", ret);
304 }
305 online = ParseInt(buf);
306 if (online) {
307 onlineNode = *iter;
308 break;
309 }
310 iter++;
311 }
312
313 ret = ReadSysfsFile(onlinePath.c_str(), buf, size);
314 if (ret != HDF_SUCCESS) {
315 BATTERY_HILOGW(FEATURE_BATT_INFO, "read online path failed, ret: %{public}d", ret);
316 return;
317 }
318
319 online = ParseInt(buf);
320 if (!online) {
321 BATTERY_HILOGW(FEATURE_BATT_INFO, "charger is not online, so no type return");
322 return;
323 }
324
325 std::string typeNode = onlineNode;
326 std::string typePath = path_ + "/" + typeNode + "/" + "type";
327 ret = ReadSysfsFile(typePath.c_str(), buf, size);
328 if (ret != HDF_SUCCESS) {
329 BATTERY_HILOGW(FEATURE_BATT_INFO, "read type path failed, ret: %{public}d", ret);
330 return;
331 }
332 Trim(buf);
333 }
334
PluggedTypeEnumConverter(const char * str) const335 int32_t PowerSupplyProvider::PluggedTypeEnumConverter(const char* str) const
336 {
337 struct StringEnumMap pluggedTypeEnumMap[] = {
338 { "USB", PLUGGED_TYPE_USB },
339 { "USB_PD_DRP", PLUGGED_TYPE_USB },
340 { "Wireless", PLUGGED_TYPE_WIRELESS },
341 { "Mains", PLUGGED_TYPE_AC },
342 { "UPS", PLUGGED_TYPE_AC },
343 { "USB_ACA", PLUGGED_TYPE_AC },
344 { "USB_C", PLUGGED_TYPE_AC },
345 { "USB_CDP", PLUGGED_TYPE_AC },
346 { "USB_DCP", PLUGGED_TYPE_AC },
347 { "USB_HVDCP", PLUGGED_TYPE_AC },
348 { "USB_PD", PLUGGED_TYPE_AC },
349 { "Unknown", PLUGGED_TYPE_BUTT },
350 { nullptr, PLUGGED_TYPE_BUTT },
351 };
352
353 for (int32_t i = 0; pluggedTypeEnumMap[i].str; ++i) {
354 if (strcmp(str, pluggedTypeEnumMap[i].str) == 0) {
355 return pluggedTypeEnumMap[i].enumVal;
356 }
357 }
358 return PLUGGED_TYPE_BUTT;
359 }
360
ParsePluggedMaxCurrent(int32_t * maxCurrent) const361 int32_t PowerSupplyProvider::ParsePluggedMaxCurrent(int32_t* maxCurrent) const
362 {
363 char buf[MAX_BUFF_SIZE] = {0};
364 GetPluggedTypeName(buf, sizeof(buf));
365 std::string currentMaxNode = POWER_SUPPLY_BATTERY;
366
367 const auto& item = nodeNamePathMap_.find("current_max");
368 if (item != nodeNamePathMap_.end()) {
369 currentMaxNode = item->second;
370 }
371
372 std::string currentMaxPath = POWER_SUPPLY_BASE_PATH + "/" + currentMaxNode + "/" + "current_max";
373 int32_t ret = ReadBatterySysfsToBuff(currentMaxPath.c_str(), buf, sizeof(buf));
374 if (ret != HDF_SUCCESS) {
375 return ret;
376 }
377 int32_t value = ParseInt(buf);
378 *maxCurrent = value;
379
380 return HDF_SUCCESS;
381 }
382
ParsePluggedMaxVoltage(int32_t * maxVoltage) const383 int32_t PowerSupplyProvider::ParsePluggedMaxVoltage(int32_t* maxVoltage) const
384 {
385 char buf[MAX_BUFF_SIZE] = {0};
386 GetPluggedTypeName(buf, sizeof(buf));
387 std::string voltageMaxNode = POWER_SUPPLY_BATTERY;
388
389 const auto& item = nodeNamePathMap_.find("voltage_max");
390 if (item != nodeNamePathMap_.end()) {
391 voltageMaxNode = item->second;
392 }
393
394 std::string voltageMaxPath = POWER_SUPPLY_BASE_PATH + "/" + voltageMaxNode + "/" + "voltage_max";
395 int32_t ret = ReadBatterySysfsToBuff(voltageMaxPath.c_str(), buf, sizeof(buf));
396 if (ret != HDF_SUCCESS) {
397 return ret;
398 }
399 int32_t value = ParseInt(buf);
400 *maxVoltage = value;
401
402 return HDF_SUCCESS;
403 }
404
UpdateInfoByReadSysFile(struct BatterydInfo * info) const405 void PowerSupplyProvider::UpdateInfoByReadSysFile(struct BatterydInfo* info) const
406 {
407 ParseCapacity(&info->capacity_);
408 ParseVoltage(&info->voltage_);
409 ParseTemperature(&info->temperature_);
410 ParseHealthState(&info->healthState_);
411 ParseChargeState(&info->chargeState_);
412 ParseChargeCounter(&info->chargeCounter_);
413 ParseCurrentNow(&info->curNow_);
414 ParseCurrentAverage(&info->curAverage_);
415 ParseRemainEnergy(&info->remainEnergy_);
416 ParseTotalEnergy(&info->totalEnergy_);
417 ParsePresent(&info->present_);
418
419 info->pluggedType_ = PLUGGED_TYPE_NONE;
420 ParsePluggedType(&info->pluggedType_);
421
422 info->pluggedMaxCurrent_ = INVALID_BATT_INT_VALUE;
423 ParsePluggedMaxCurrent(&info->pluggedMaxCurrent_);
424
425 info->pluggedMaxVoltage_ = INVALID_BATT_INT_VALUE;
426 ParsePluggedMaxVoltage(&info->pluggedMaxVoltage_);
427
428 info->technology_ = INVALID_STRING_VALUE;
429 ParseTechnology(info->technology_);
430
431 CopyBatteryInfo(info);
432 }
433
ParseUeventToBatterydInfo(const char * msg,struct BatterydInfo * info) const434 void PowerSupplyProvider::ParseUeventToBatterydInfo(const char* msg, struct BatterydInfo* info) const
435 {
436 static struct BatteryAssigner batteryAssigners[] = {
437 { BATTERY_KEY_CAPACITY.c_str(), BATTERY_KEY_CAPACITY.length(), CapacityAssigner },
438 { BATTERY_KEY_TOTAL_ENERGY.c_str(), BATTERY_KEY_TOTAL_ENERGY.length(), TotalEnergyAssigner },
439 { BATTERY_KEY_REMAIN_ENERGY.c_str(), BATTERY_KEY_REMAIN_ENERGY.length(), RemainEnergyAssigner },
440 { BATTERY_KEY_VOLTAGE.c_str(), BATTERY_KEY_VOLTAGE.length(), VoltageAssigner },
441 { BATTERY_KEY_TEMPERATURE.c_str(), BATTERY_KEY_TEMPERATURE.length(), TemperatureAssigner },
442 { BATTERY_KEY_HEALTH.c_str(), BATTERY_KEY_HEALTH.length(), HealthStateAssigner },
443 { BATTERY_KEY_CHARGE_STATUS.c_str(), BATTERY_KEY_CHARGE_STATUS.length(), ChargeStateAssigner },
444 { BATTERY_KEY_PRESENT.c_str(), BATTERY_KEY_PRESENT.length(), PresentAssigner },
445 { BATTERY_KEY_TECHNOLOGY.c_str(), BATTERY_KEY_TECHNOLOGY.length(), TechnologyAssigner },
446 { BATTERY_KEY_CHARGE_COUNTER.c_str(), BATTERY_KEY_CHARGE_COUNTER.length(), ChargeCounterAssigner },
447 { BATTERY_KEY_CURRENT_AVERAGE.c_str(), BATTERY_KEY_CURRENT_AVERAGE.length(), CurrentAverageAssigner },
448 { BATTERY_KEY_CURRENT_NOW.c_str(), BATTERY_KEY_CURRENT_NOW.length(), CurrentNowAssigner },
449 { nullptr, 0, nullptr } // end of the array
450 };
451
452 while (*msg) {
453 for (int32_t i = 0; batteryAssigners[i].prefix; ++i) {
454 if (!strncmp(msg, batteryAssigners[i].prefix, batteryAssigners[i].prefixLen)) {
455 BATTERY_HILOGD(FEATURE_BATT_INFO, "msg: %{public}s", msg);
456 msg += batteryAssigners[i].prefixLen;
457 batteryAssigners[i].Assigner(msg, info);
458 break;
459 }
460 }
461 while (*msg++) {} // move to next
462 }
463
464 info->pluggedType_ = PLUGGED_TYPE_NONE;
465 ParsePluggedType(&info->pluggedType_);
466
467 info->pluggedMaxCurrent_ = INVALID_BATT_INT_VALUE;
468 ParsePluggedMaxCurrent(&info->pluggedMaxCurrent_);
469
470 info->pluggedMaxVoltage_ = INVALID_BATT_INT_VALUE;
471 ParsePluggedMaxVoltage(&info->pluggedMaxVoltage_);
472
473 info->technology_ = INVALID_STRING_VALUE;
474 ParseTechnology(info->technology_);
475
476 CopyBatteryInfo(info);
477 }
478
CopyBatteryInfo(const struct BatterydInfo * info) const479 void PowerSupplyProvider::CopyBatteryInfo(const struct BatterydInfo* info) const
480 {
481 g_batteryInfo.capacity_ = info->capacity_;
482 g_batteryInfo.voltage_ = info->voltage_;
483 g_batteryInfo.temperature_ = info->temperature_;
484 g_batteryInfo.healthState_ = info->healthState_;
485 g_batteryInfo.pluggedType_ = info->pluggedType_;
486 g_batteryInfo.pluggedMaxCurrent_ = info->pluggedMaxCurrent_;
487 g_batteryInfo.pluggedMaxVoltage_ = info->pluggedMaxVoltage_;
488 g_batteryInfo.chargeState_ = info->chargeState_;
489 g_batteryInfo.chargeCounter_ = info->chargeCounter_;
490 g_batteryInfo.curNow_ = info->curNow_;
491 g_batteryInfo.curAverage_ = info->curAverage_;
492 g_batteryInfo.totalEnergy_ = info->totalEnergy_;
493 g_batteryInfo.remainEnergy_ = info->remainEnergy_;
494 g_batteryInfo.present_ = info->present_;
495 g_batteryInfo.technology_ = info->technology_;
496 }
497
SetSysFilePath(const std::string & path)498 void PowerSupplyProvider::SetSysFilePath(const std::string& path)
499 {
500 if (path.empty()) {
501 BATTERY_HILOGI(FEATURE_BATT_INFO, "path is empty");
502 return;
503 }
504 path_ = path;
505 }
506
CreateFile(const std::string & path,const std::string & content)507 void PowerSupplyProvider::CreateFile(const std::string& path, const std::string& content)
508 {
509 if (access(path.c_str(), F_OK) == 0) {
510 return;
511 }
512
513 std::ofstream stream(path.c_str());
514 if (!stream.is_open()) {
515 BATTERY_HILOGE(FEATURE_BATT_INFO, "cannot create file");
516 return;
517 }
518 stream << content.c_str() << std::endl;
519 stream.close();
520 }
521
InitBatteryPath()522 void PowerSupplyProvider::InitBatteryPath()
523 {
524 std::string sysLowercaseBatteryPath = "/sys/class/power_supply/battery";
525
526 if (access(sysLowercaseBatteryPath.c_str(), F_OK) == 0) {
527 BATTERY_HILOGI(FEATURE_BATT_INFO, "system battery path is exist");
528 return;
529 } else {
530 std::string sysCapitalBatteryPath = "/sys/class/power_supply/Battery";
531 if (access(sysCapitalBatteryPath.c_str(), F_OK) == 0) {
532 BATTERY_HILOGI(FEATURE_BATT_INFO, "system Battery path is exist");
533 return;
534 }
535 InitDefaultSysfs();
536 }
537 InitChargerSysfs();
538 }
539
InitPowerSupplySysfs()540 int32_t PowerSupplyProvider::InitPowerSupplySysfs()
541 {
542 DIR* dir = nullptr;
543 struct dirent* entry = nullptr;
544 index_ = 0;
545
546 dir = opendir(path_.c_str());
547 if (dir == nullptr) {
548 BATTERY_HILOGE(FEATURE_BATT_INFO, "cannot open path_");
549 return HDF_ERR_IO;
550 }
551
552 while (true) {
553 entry = readdir(dir);
554 if (entry == nullptr) {
555 break;
556 }
557
558 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
559 continue;
560 }
561
562 if (entry->d_type == DT_DIR || entry->d_type == DT_LNK) {
563 if (index_ >= MAX_SYSFS_SIZE) {
564 BATTERY_HILOGW(FEATURE_BATT_INFO, "too many power supply types");
565 break;
566 }
567 nodeNames_.emplace_back(entry->d_name);
568 index_++;
569 }
570 }
571 nodeNamePathMap_.clear();
572 TraversalNode();
573 FormatSysfsPaths();
574 BATTERY_HILOGD(FEATURE_BATT_INFO, "init power supply sysfs nodes, total count %{public}d", index_);
575 closedir(dir);
576
577 return HDF_SUCCESS;
578 }
579
InitChargerSysfs()580 void PowerSupplyProvider::InitChargerSysfs()
581 {
582 auto& batteryConfig = BatteryConfig::GetInstance();
583 batteryConfig.ParseConfig();
584 std::string mockCurrentLimitPath = batteryConfig.GetString("charger.current_limit.path");
585 std::string mockVoltageLimitPath = batteryConfig.GetString("charger.voltage_limit.path");
586 std::string mockChargeTypePath = batteryConfig.GetString("charger.type.path");
587
588 if (access(mockCurrentLimitPath.c_str(), 0) == -1) {
589 CreateFile(mockCurrentLimitPath, "0");
590 }
591
592 if (access(mockVoltageLimitPath.c_str(), 0) == -1) {
593 CreateFile(mockVoltageLimitPath, "0");
594 }
595
596 if (access(mockChargeTypePath.c_str(), 0) == -1) {
597 CreateFile(mockChargeTypePath, "0");
598 }
599 }
600
TraversalNode()601 void PowerSupplyProvider::TraversalNode()
602 {
603 nodeNamePathMap_.insert(std::make_pair("type", ""));
604 nodeNamePathMap_.insert(std::make_pair("online", ""));
605 nodeNamePathMap_.insert(std::make_pair("current_max", ""));
606 nodeNamePathMap_.insert(std::make_pair("voltage_max", ""));
607 nodeNamePathMap_.insert(std::make_pair("capacity", ""));
608 nodeNamePathMap_.insert(std::make_pair("voltage_now", ""));
609 nodeNamePathMap_.insert(std::make_pair("temp", ""));
610 nodeNamePathMap_.insert(std::make_pair("health", ""));
611 nodeNamePathMap_.insert(std::make_pair("status", ""));
612 nodeNamePathMap_.insert(std::make_pair("present", ""));
613 nodeNamePathMap_.insert(std::make_pair("charge_counter", ""));
614 nodeNamePathMap_.insert(std::make_pair("technology", ""));
615 nodeNamePathMap_.insert(std::make_pair("charge_full", ""));
616 nodeNamePathMap_.insert(std::make_pair("current_avg", ""));
617 nodeNamePathMap_.insert(std::make_pair("current_now", ""));
618 nodeNamePathMap_.insert(std::make_pair("charge_now", ""));
619
620 auto iter = nodeNames_.begin();
621 while (iter != nodeNames_.end()) {
622 if (*iter == "battery") {
623 CheckSubfolderNode(*iter);
624 iter = nodeNames_.erase(iter);
625 } else {
626 iter++;
627 }
628 }
629
630 iter = nodeNames_.begin();
631 while (iter != nodeNames_.end()) {
632 if (*iter == POWER_SUPPLY_BATTERY) {
633 CheckSubfolderNode(*iter);
634 iter = nodeNames_.erase(iter);
635 } else {
636 iter++;
637 }
638 }
639
640 for (auto& nodeName : nodeNames_) {
641 CheckSubfolderNode(nodeName);
642 }
643 }
644
CheckSubfolderNode(const std::string & path)645 void PowerSupplyProvider::CheckSubfolderNode(const std::string& path)
646 {
647 DIR *dir = nullptr;
648 struct dirent* entry = nullptr;
649 std::string batteryPath = path_ + "/" + path;
650
651 dir = opendir(batteryPath.c_str());
652 if (dir == nullptr) {
653 BATTERY_HILOGE(FEATURE_BATT_INFO, "subfolder file is not exist.");
654 return;
655 }
656
657 while (true) {
658 entry = readdir(dir);
659 if (entry == nullptr) {
660 break;
661 }
662
663 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
664 continue;
665 }
666
667 if (entry->d_type == DT_DIR || entry->d_type == DT_LNK) {
668 continue;
669 }
670
671 if ((strcmp(entry->d_name, "type") == 0) && (nodeNamePathMap_["type"].empty()) &&
672 (strcasecmp(path.c_str(), BATTERY_NODE_PATH.c_str()) != 0)) {
673 nodeNamePathMap_["type"] = path;
674 }
675
676 for (auto & iter : nodeNamePathMap_) {
677 if ((strcmp(entry->d_name, iter.first.c_str()) == 0) && (nodeNamePathMap_[iter.first].empty())) {
678 nodeNamePathMap_[iter.first] = path;
679 }
680 }
681 }
682 closedir(dir);
683 }
684
ParseCapacity(int32_t * capacity) const685 int32_t PowerSupplyProvider::ParseCapacity(int32_t* capacity) const
686 {
687 char buf[MAX_BUFF_SIZE] = {0};
688
689 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.capacityPath.c_str(), buf, sizeof(buf));
690 if (ret != HDF_SUCCESS) {
691 return ret;
692 }
693
694 int32_t value = ParseInt(buf);
695 *capacity = value;
696
697 return HDF_SUCCESS;
698 }
699
ParseTotalEnergy(int32_t * totalEnergy) const700 int32_t PowerSupplyProvider::ParseTotalEnergy(int32_t* totalEnergy) const
701 {
702 char buf[MAX_BUFF_SIZE] = {0};
703
704 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.totalEnergyPath.c_str(), buf, sizeof(buf));
705 if (ret != HDF_SUCCESS) {
706 return ret;
707 }
708
709 int32_t value = ParseInt(buf);
710 *totalEnergy = value;
711
712 return HDF_SUCCESS;
713 }
714
ParseCurrentAverage(int32_t * curAverage) const715 int32_t PowerSupplyProvider::ParseCurrentAverage(int32_t* curAverage) const
716 {
717 char buf[MAX_BUFF_SIZE] = {0};
718
719 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.curAveragePath.c_str(), buf, sizeof(buf));
720 if (ret != HDF_SUCCESS) {
721 return ret;
722 }
723
724 int32_t value = ParseInt(buf);
725 *curAverage = value;
726
727 return HDF_SUCCESS;
728 }
729
ParseCurrentNow(int32_t * curNow) const730 int32_t PowerSupplyProvider::ParseCurrentNow(int32_t* curNow) const
731 {
732 char buf[MAX_BUFF_SIZE] = {0};
733
734 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.curNowPath.c_str(), buf, sizeof(buf));
735 if (ret != HDF_SUCCESS) {
736 return ret;
737 }
738
739 int32_t value = ParseInt(buf);
740 *curNow = value;
741
742 return HDF_SUCCESS;
743 }
744
ParseRemainEnergy(int32_t * remainEnergy) const745 int32_t PowerSupplyProvider::ParseRemainEnergy(int32_t* remainEnergy) const
746 {
747 char buf[MAX_BUFF_SIZE] = {0};
748
749 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.remainEnergyPath.c_str(), buf, sizeof(buf));
750 if (ret != HDF_SUCCESS) {
751 return ret;
752 }
753
754 int32_t value = ParseInt(buf);
755 *remainEnergy = value;
756
757 return HDF_SUCCESS;
758 }
759
ParseVoltage(int32_t * voltage) const760 int32_t PowerSupplyProvider::ParseVoltage(int32_t* voltage) const
761 {
762 char buf[MAX_BUFF_SIZE] = {0};
763 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.voltagePath.c_str(), buf, sizeof(buf));
764 if (ret != HDF_SUCCESS) {
765 return ret;
766 }
767
768 int32_t value = ParseInt(buf);
769 *voltage = value;
770
771 return HDF_SUCCESS;
772 }
773
ParseTemperature(int32_t * temperature) const774 int32_t PowerSupplyProvider::ParseTemperature(int32_t* temperature) const
775 {
776 char buf[MAX_BUFF_SIZE] = {0};
777 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.temperaturePath.c_str(), buf, sizeof(buf));
778 if (ret != HDF_SUCCESS) {
779 return ret;
780 }
781
782 int32_t value = ParseInt(buf);
783 *temperature = value;
784
785 return HDF_SUCCESS;
786 }
787
ParseHealthState(int32_t * healthState) const788 int32_t PowerSupplyProvider::ParseHealthState(int32_t* healthState) const
789 {
790 char buf[MAX_BUFF_SIZE] = {0};
791 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.healthStatePath.c_str(), buf, sizeof(buf));
792 if (ret != HDF_SUCCESS) {
793 return ret;
794 }
795
796 Trim(buf);
797 *healthState = HealthStateEnumConverter(buf);
798 return HDF_SUCCESS;
799 }
800
ParsePluggedType(int32_t * pluggedType) const801 int32_t PowerSupplyProvider::ParsePluggedType(int32_t* pluggedType) const
802 {
803 char buf[MAX_BUFF_SIZE] = {0};
804 GetPluggedTypeName(buf, sizeof(buf));
805 int32_t type = PluggedTypeEnumConverter(buf);
806 if (type == PLUGGED_TYPE_BUTT) {
807 BATTERY_HILOGW(FEATURE_BATT_INFO, "not support the online type %{public}s", buf);
808 return HDF_ERR_NOT_SUPPORT;
809 }
810
811 *pluggedType = type;
812 return HDF_SUCCESS;
813 }
814
ParseChargeState(int32_t * chargeState) const815 int32_t PowerSupplyProvider::ParseChargeState(int32_t* chargeState) const
816 {
817 char buf[MAX_BUFF_SIZE] = {0};
818 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.chargeStatePath.c_str(), buf, sizeof(buf));
819 if (ret != HDF_SUCCESS) {
820 return ret;
821 }
822
823 Trim(buf);
824 *chargeState = ChargeStateEnumConverter(buf);
825 return HDF_SUCCESS;
826 }
827
ParsePresent(int8_t * present) const828 int32_t PowerSupplyProvider::ParsePresent(int8_t* present) const
829 {
830 char buf[MAX_BUFF_SIZE] = {0};
831 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.presentPath.c_str(), buf, sizeof(buf));
832 if (ret != HDF_SUCCESS) {
833 return ret;
834 }
835
836 auto value = static_cast<int8_t>(ParseInt(buf));
837 *present = value;
838 return HDF_SUCCESS;
839 }
840
ParseChargeCounter(int32_t * chargeCounter) const841 int32_t PowerSupplyProvider::ParseChargeCounter(int32_t* chargeCounter) const
842 {
843 char buf[MAX_BUFF_SIZE] = {0};
844 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.chargeCounterPath.c_str(), buf, sizeof(buf));
845 if (ret != HDF_SUCCESS) {
846 return ret;
847 }
848
849 int32_t value = ParseInt(buf);
850 *chargeCounter = value;
851
852 return HDF_SUCCESS;
853 }
854
ParseTechnology(std::string & technology) const855 int32_t PowerSupplyProvider::ParseTechnology(std::string& technology) const
856 {
857 char buf[MAX_BUFF_SIZE] = {0};
858 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.technologyPath.c_str(), buf, sizeof(buf));
859 if (ret != HDF_SUCCESS) {
860 return ret;
861 }
862
863 technology.assign(buf, strlen(buf));
864 return HDF_SUCCESS;
865 }
866
ParseChargeType(int32_t * chargeType,std::string & chargeTypePath) const867 int32_t PowerSupplyProvider::ParseChargeType(int32_t* chargeType, std::string& chargeTypePath) const
868 {
869 char buf[MAX_BUFF_SIZE] = {0};
870 int32_t ret = ReadBatterySysfsToBuff(chargeTypePath.c_str(), buf, sizeof(buf));
871 if (ret != HDF_SUCCESS) {
872 return ret;
873 }
874
875 Trim(buf);
876 *chargeType = ChargeTypeEumConverter(buf);
877 return HDF_SUCCESS;
878 }
879
GetBatteryInfo() const880 BatterydInfo PowerSupplyProvider::GetBatteryInfo() const
881 {
882 UpdateInfoByReadSysFile(&g_batteryInfo);
883 return g_batteryInfo;
884 }
885
CreateMockTechPath(std::string & mockTechPath)886 void PowerSupplyProvider::CreateMockTechPath(std::string& mockTechPath)
887 {
888 BATTERY_HILOGI(FEATURE_BATT_INFO, "create mockFilePath path");
889 CreateFile(mockTechPath + "/capacity", "1000");
890 CreateFile(mockTechPath + "/current_avg", "1000");
891 CreateFile(mockTechPath + "/current_now", "1000");
892 CreateFile(mockTechPath + "/health", "Over voltage");
893 CreateFile(mockTechPath + "/present", "0");
894 CreateFile(mockTechPath + "/status", "Not charging");
895 CreateFile(mockTechPath + "/type", "Unknown");
896 CreateFile(mockTechPath + "/temp", "345");
897 CreateFile(mockTechPath + "/technology", "Li-ion");
898 }
899
CreateMockChargerPath(std::string & mockChargerPath)900 void PowerSupplyProvider::CreateMockChargerPath(std::string& mockChargerPath)
901 {
902 BATTERY_HILOGI(FEATURE_BATT_INFO, "create mockFilePath path");
903 CreateFile(mockChargerPath + "/type", "USB");
904 CreateFile(mockChargerPath + "/constant_charge_current", "0");
905 CreateFile(mockChargerPath + "/health", "Good");
906 CreateFile(mockChargerPath + "/online", "1");
907 CreateFile(mockChargerPath + "/status", "Charging");
908 }
909
CreateMockBatteryPath(std::string & mockBatteryPath)910 void PowerSupplyProvider::CreateMockBatteryPath(std::string& mockBatteryPath)
911 {
912 BATTERY_HILOGI(FEATURE_BATT_INFO, "create mockFilePath path");
913 CreateFile(mockBatteryPath + "/capacity", "11");
914 CreateFile(mockBatteryPath + "/charge_control_limit", "0");
915 CreateFile(mockBatteryPath + "/charge_counter", "4000000");
916 CreateFile(mockBatteryPath + "/charge_full", "4000000");
917 CreateFile(mockBatteryPath + "/charge_now", "4000000");
918 CreateFile(mockBatteryPath + "/constant_charge_current", "0");
919 CreateFile(mockBatteryPath + "/current_avg", "1000");
920 CreateFile(mockBatteryPath + "/current_now", "1000");
921 CreateFile(mockBatteryPath + "/health", "Good");
922 CreateFile(mockBatteryPath + "/input_current_limit", "0");
923 CreateFile(mockBatteryPath + "/online", "1");
924 CreateFile(mockBatteryPath + "/present", "0");
925 CreateFile(mockBatteryPath + "/status", "Charging");
926 CreateFile(mockBatteryPath + "/temp", "222");
927 CreateFile(mockBatteryPath + "/voltage_avg", "4123456");
928 CreateFile(mockBatteryPath + "/voltage_now", "4123456");
929 CreateFile(mockBatteryPath + "/type", "Battery");
930 }
931
InitDefaultSysfs()932 void PowerSupplyProvider::InitDefaultSysfs()
933 {
934 std::string mockBatteryPath = MOCK_POWER_SUPPLY_BASE_PATH + "/battery";
935 std::string mockChargerPath = MOCK_POWER_SUPPLY_BASE_PATH + "/ohos_charger";
936 std::string mockTechPath = MOCK_POWER_SUPPLY_BASE_PATH + "/ohos-fgu";
937
938 if (access(mockBatteryPath.c_str(), 0) == -1) {
939 mkdir(mockBatteryPath.c_str(), S_IRWXU | S_IRWXG);
940 sleep(MKDIR_WAIT_TIME);
941 }
942
943 if (access(mockChargerPath.c_str(), 0) == -1) {
944 mkdir(mockChargerPath.c_str(), S_IRWXU);
945 sleep(MKDIR_WAIT_TIME);
946 }
947
948 if (access(mockTechPath.c_str(), 0) == -1) {
949 mkdir(mockTechPath.c_str(), S_IRWXU);
950 sleep(MKDIR_WAIT_TIME);
951 }
952
953 CreateMockTechPath(mockTechPath);
954 CreateMockChargerPath(mockChargerPath);
955 CreateMockBatteryPath(mockBatteryPath);
956 path_ = MOCK_POWER_SUPPLY_BASE_PATH;
957 }
958
SetChargingLimit(const std::vector<ChargingLimit> & chargerLimitList,std::string & currentPath,std::string & voltagePath)959 int32_t PowerSupplyProvider::SetChargingLimit(const std::vector<ChargingLimit>& chargerLimitList,
960 std::string& currentPath, std::string& voltagePath)
961 {
962 BATTERY_HILOGD(FEATURE_BATT_INFO, "enter");
963 if (chargerLimitList.empty()) {
964 BATTERY_HILOGE(FEATURE_BATT_INFO, "the parameter is empty");
965 return HDF_ERR_INVALID_PARAM;
966 }
967
968 std::string limitPath;
969 std::string chargeLimitStr;
970 for (const auto& iter : chargerLimitList) {
971 if (iter.type == ChargingLimitType::TYPE_CURRENT) {
972 limitPath = currentPath;
973 } else if (iter.type == ChargingLimitType::TYPE_VOLTAGE) {
974 limitPath = voltagePath;
975 }
976 chargeLimitStr = chargeLimitStr + (iter.protocol + " " + std::to_string(iter.value) + "\n");
977 }
978 int32_t ret = WriteChargingLimit(limitPath, chargeLimitStr);
979 if (ret < HDF_SUCCESS) {
980 return ret;
981 }
982 BATTERY_HILOGI(FEATURE_BATT_INFO, "Exit");
983 return HDF_SUCCESS;
984 }
985
WriteChargingLimit(std::string chargingLimitPath,std::string & str)986 int32_t PowerSupplyProvider::WriteChargingLimit(std::string chargingLimitPath, std::string& str)
987 {
988 BATTERY_HILOGI(FEATURE_BATT_INFO, "Enter");
989 std::fstream out(chargingLimitPath, std::ios::out | std::ios::trunc);
990 out << str;
991 out.close();
992 BATTERY_HILOGI(FEATURE_BATT_INFO, "Exit");
993 return HDF_SUCCESS;
994 }
995 } // namespace V1_2
996 } // namespace Battery
997 } // namespace HDI
998 } // namespace OHOS
999