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 "osal/osal_mem.h"
25 #include "battery_log.h"
26 #include "battery_config.h"
27
28 namespace OHOS {
29 namespace HDI {
30 namespace Battery {
31 namespace V1_1 {
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
ChargeStateAssigner(const char * str,struct BatterydInfo * info)167 inline void PowerSupplyProvider::ChargeStateAssigner(const char* str, struct BatterydInfo* info)
168 {
169 info->chargeState_ = ChargeStateEnumConverter(str);
170 }
171
PresentAssigner(const char * str,struct BatterydInfo * info)172 inline void PowerSupplyProvider::PresentAssigner(const char* str, struct BatterydInfo* info)
173 {
174 info->present_ = static_cast<int8_t>(ParseInt(str));
175 }
176
TechnologyAssigner(const char * str,struct BatterydInfo * info)177 inline void PowerSupplyProvider::TechnologyAssigner(const char* str, struct BatterydInfo* info)
178 {
179 info->technology_ = str;
180 }
181
ChargeCounterAssigner(const char * str,struct BatterydInfo * info)182 inline void PowerSupplyProvider::ChargeCounterAssigner(const char* str, struct BatterydInfo* info)
183 {
184 info->chargeCounter_ = ParseInt(str);
185 }
186
CurrentAverageAssigner(const char * str,struct BatterydInfo * info)187 inline void PowerSupplyProvider::CurrentAverageAssigner(const char* str, struct BatterydInfo* info)
188 {
189 info->curAverage_ = ParseInt(str);
190 }
191
CurrentNowAssigner(const char * str,struct BatterydInfo * info)192 inline void PowerSupplyProvider::CurrentNowAssigner(const char* str, struct BatterydInfo* info)
193 {
194 info->curNow_ = ParseInt(str);
195 }
196
FormatPath(std::string & path,size_t size,const char * format,const char * basePath,const char * name) const197 void PowerSupplyProvider::FormatPath(std::string& path,
198 size_t size, const char* format, const char* basePath, const char* name) const
199 {
200 char buff[PATH_MAX] = {0};
201 if (strcpy_s(buff, PATH_MAX, path.c_str()) != EOK) {
202 BATTERY_HILOGW(FEATURE_BATT_INFO, "failed to copy path of %{public}s", name);
203 return;
204 }
205
206 if (snprintf_s(buff, PATH_MAX, size - 1, format, basePath, name) == -1) {
207 BATTERY_HILOGW(FEATURE_BATT_INFO, "failed to format path of %{public}s", name);
208 return;
209 }
210 path.assign(buff, strlen(buff));
211 }
212
FormatSysfsPaths(struct PowerSupplySysfsInfo * info)213 void PowerSupplyProvider::FormatSysfsPaths(struct PowerSupplySysfsInfo *info)
214 {
215 // Format paths for power supply types
216 FormatPath(info->typePath, PATH_MAX, "%s/%s/type", path_.c_str(), nodeNamePathMap_["type"].c_str());
217 FormatPath(info->onlinePath, PATH_MAX, "%s/%s/online", path_.c_str(), nodeNamePathMap_["online"].c_str());
218 FormatPath(info->currentMaxPath, PATH_MAX, "%s/%s/current_max", path_.c_str(),
219 nodeNamePathMap_["current_max"].c_str());
220 FormatPath(info->voltageMaxPath, PATH_MAX, "%s/%s/voltage_max", path_.c_str(),
221 nodeNamePathMap_["voltage_max"].c_str());
222 FormatPath(batterySysfsInfo_.capacityPath, PATH_MAX, "%s/%s/capacity", path_.c_str(),
223 nodeNamePathMap_["capacity"].c_str());
224 FormatPath(batterySysfsInfo_.voltagePath, PATH_MAX, "%s/%s/voltage_now", path_.c_str(),
225 nodeNamePathMap_["voltage_now"].c_str());
226 FormatPath(batterySysfsInfo_.temperaturePath, PATH_MAX, "%s/%s/temp", path_.c_str(),
227 nodeNamePathMap_["temp"].c_str());
228 FormatPath(batterySysfsInfo_.healthStatePath, PATH_MAX, "%s/%s/health", path_.c_str(),
229 nodeNamePathMap_["health"].c_str());
230 FormatPath(batterySysfsInfo_.chargeStatePath, PATH_MAX, "%s/%s/status", path_.c_str(),
231 nodeNamePathMap_["status"].c_str());
232 FormatPath(batterySysfsInfo_.presentPath, PATH_MAX, "%s/%s/present", path_.c_str(),
233 nodeNamePathMap_["present"].c_str());
234 FormatPath(batterySysfsInfo_.chargeCounterPath, PATH_MAX, "%s/%s/charge_counter", path_.c_str(),
235 nodeNamePathMap_["charge_counter"].c_str());
236 FormatPath(batterySysfsInfo_.technologyPath, PATH_MAX, "%s/%s/technology", path_.c_str(),
237 nodeNamePathMap_["technology"].c_str());
238 FormatPath(batterySysfsInfo_.totalEnergyPath, PATH_MAX, "%s/%s/charge_full", path_.c_str(),
239 nodeNamePathMap_["charge_full"].c_str());
240 FormatPath(batterySysfsInfo_.curAveragePath, PATH_MAX, "%s/%s/current_avg", path_.c_str(),
241 nodeNamePathMap_["current_avg"].c_str());
242 FormatPath(batterySysfsInfo_.curNowPath, PATH_MAX, "%s/%s/current_now", path_.c_str(),
243 nodeNamePathMap_["current_now"].c_str());
244 FormatPath(batterySysfsInfo_.remainEnergyPath, PATH_MAX, "%s/%s/charge_now", path_.c_str(),
245 nodeNamePathMap_["charge_now"].c_str());
246 }
247
ReadSysfsFile(const char * path,char * buf,size_t size) const248 int32_t PowerSupplyProvider::ReadSysfsFile(const char* path, char* buf, size_t size) const
249 {
250 int32_t fd = open(path, O_RDONLY, S_IRUSR | S_IRGRP | S_IROTH);
251 if (fd < NUM_ZERO) {
252 BATTERY_HILOGE(FEATURE_BATT_INFO, "failed to open SysfsFile");
253 return HDF_ERR_IO;
254 }
255
256 size_t readSize = read(fd, buf, size - 1);
257 buf[readSize] = '\0';
258 Trim(buf);
259 close(fd);
260
261 return HDF_SUCCESS;
262 }
263
ReadBatterySysfsToBuff(const char * path,char * buf,size_t size) const264 int32_t PowerSupplyProvider::ReadBatterySysfsToBuff(const char* path, char* buf, size_t size) const
265 {
266 int32_t ret = ReadSysfsFile(path, buf, size);
267 if (ret != HDF_SUCCESS) {
268 BATTERY_HILOGW(FEATURE_BATT_INFO, "read path failed, ret: %{public}d", ret);
269 return ret;
270 }
271
272 return HDF_SUCCESS;
273 }
274
GetPluggedTypeName(char * buf,size_t size) const275 void PowerSupplyProvider::GetPluggedTypeName(char* buf, size_t size) const
276 {
277 std::string onlineNode = "USB";
278 int32_t ret;
279 int32_t online;
280 std::string onlinePath;
281
282 auto iter = nodeNames_.begin();
283 while (iter != nodeNames_.end()) {
284 onlinePath = path_ + "/" + *iter + "/" + "online";
285 ret = ReadSysfsFile(onlinePath.c_str(), buf, size);
286 if (ret != HDF_SUCCESS) {
287 BATTERY_HILOGW(FEATURE_BATT_INFO, "read online path failed in loop, ret: %{public}d", ret);
288 }
289 online = ParseInt(buf);
290 if (online) {
291 onlineNode = *iter;
292 break;
293 }
294 iter++;
295 }
296
297 ret = ReadSysfsFile(onlinePath.c_str(), buf, size);
298 if (ret != HDF_SUCCESS) {
299 BATTERY_HILOGW(FEATURE_BATT_INFO, "read online path failed, ret: %{public}d", ret);
300 return;
301 }
302
303 online = ParseInt(buf);
304 if (!online) {
305 BATTERY_HILOGW(FEATURE_BATT_INFO, "charger is not online, so no type return");
306 return;
307 }
308
309 std::string typeNode = onlineNode;
310 std::string typePath = path_ + "/" + typeNode + "/" + "type";
311 ret = ReadSysfsFile(typePath.c_str(), buf, size);
312 if (ret != HDF_SUCCESS) {
313 BATTERY_HILOGW(FEATURE_BATT_INFO, "read type path failed, ret: %{public}d", ret);
314 return;
315 }
316 Trim(buf);
317 }
318
PluggedTypeEnumConverter(const char * str) const319 int32_t PowerSupplyProvider::PluggedTypeEnumConverter(const char* str) const
320 {
321 struct StringEnumMap pluggedTypeEnumMap[] = {
322 { "USB", PLUGGED_TYPE_USB },
323 { "USB_PD_DRP", PLUGGED_TYPE_USB },
324 { "Wireless", PLUGGED_TYPE_WIRELESS },
325 { "Mains", PLUGGED_TYPE_AC },
326 { "UPS", PLUGGED_TYPE_AC },
327 { "USB_ACA", PLUGGED_TYPE_AC },
328 { "USB_C", PLUGGED_TYPE_AC },
329 { "USB_CDP", PLUGGED_TYPE_AC },
330 { "USB_DCP", PLUGGED_TYPE_AC },
331 { "USB_HVDCP", PLUGGED_TYPE_AC },
332 { "USB_PD", PLUGGED_TYPE_AC },
333 { "Unknown", PLUGGED_TYPE_BUTT },
334 { nullptr, PLUGGED_TYPE_BUTT },
335 };
336
337 for (int32_t i = 0; pluggedTypeEnumMap[i].str; ++i) {
338 if (strcmp(str, pluggedTypeEnumMap[i].str) == 0) {
339 return pluggedTypeEnumMap[i].enumVal;
340 }
341 }
342 return PLUGGED_TYPE_BUTT;
343 }
344
ParsePluggedMaxCurrent(int32_t * maxCurrent) const345 int32_t PowerSupplyProvider::ParsePluggedMaxCurrent(int32_t* maxCurrent) const
346 {
347 char buf[MAX_BUFF_SIZE] = {0};
348 GetPluggedTypeName(buf, sizeof(buf));
349 std::string currentMaxNode = POWER_SUPPLY_BATTERY;
350
351 const auto& item = nodeNamePathMap_.find("current_max");
352 if (item != nodeNamePathMap_.end()) {
353 currentMaxNode = item->second;
354 }
355
356 std::string currentMaxPath = POWER_SUPPLY_BASE_PATH + "/" + currentMaxNode + "/" + "current_max";
357 int32_t ret = ReadBatterySysfsToBuff(currentMaxPath.c_str(), buf, sizeof(buf));
358 if (ret != HDF_SUCCESS) {
359 return ret;
360 }
361 int32_t value = ParseInt(buf);
362 *maxCurrent = value;
363
364 return HDF_SUCCESS;
365 }
366
ParsePluggedMaxVoltage(int32_t * maxVoltage) const367 int32_t PowerSupplyProvider::ParsePluggedMaxVoltage(int32_t* maxVoltage) const
368 {
369 char buf[MAX_BUFF_SIZE] = {0};
370 GetPluggedTypeName(buf, sizeof(buf));
371 std::string voltageMaxNode = POWER_SUPPLY_BATTERY;
372
373 const auto& item = nodeNamePathMap_.find("voltage_max");
374 if (item != nodeNamePathMap_.end()) {
375 voltageMaxNode = item->second;
376 }
377
378 std::string voltageMaxPath = POWER_SUPPLY_BASE_PATH + "/" + voltageMaxNode + "/" + "voltage_max";
379 int32_t ret = ReadBatterySysfsToBuff(voltageMaxPath.c_str(), buf, sizeof(buf));
380 if (ret != HDF_SUCCESS) {
381 return ret;
382 }
383 int32_t value = ParseInt(buf);
384 *maxVoltage = value;
385
386 return HDF_SUCCESS;
387 }
388
UpdateInfoByReadSysFile(struct BatterydInfo * info) const389 void PowerSupplyProvider::UpdateInfoByReadSysFile(struct BatterydInfo* info) const
390 {
391 ParseCapacity(&info->capacity_);
392 ParseVoltage(&info->voltage_);
393 ParseTemperature(&info->temperature_);
394 ParseHealthState(&info->healthState_);
395 ParseChargeState(&info->chargeState_);
396 ParseChargeCounter(&info->chargeCounter_);
397 ParseCurrentNow(&info->curNow_);
398 ParseCurrentAverage(&info->curAverage_);
399 ParseRemainEnergy(&info->remainEnergy_);
400 ParseTotalEnergy(&info->totalEnergy_);
401 ParsePresent(&info->present_);
402
403 info->pluggedType_ = PLUGGED_TYPE_NONE;
404 ParsePluggedType(&info->pluggedType_);
405
406 info->pluggedMaxCurrent_ = INVALID_BATT_INT_VALUE;
407 ParsePluggedMaxCurrent(&info->pluggedMaxCurrent_);
408
409 info->pluggedMaxVoltage_ = INVALID_BATT_INT_VALUE;
410 ParsePluggedMaxVoltage(&info->pluggedMaxVoltage_);
411
412 info->technology_ = INVALID_STRING_VALUE;
413 ParseTechnology(info->technology_);
414
415 CopyBatteryInfo(info);
416 }
417
ParseUeventToBatterydInfo(const char * msg,struct BatterydInfo * info) const418 void PowerSupplyProvider::ParseUeventToBatterydInfo(const char* msg, struct BatterydInfo* info) const
419 {
420 static struct BatteryAssigner batteryAssigners[] = {
421 { BATTERY_KEY_CAPACITY.c_str(), BATTERY_KEY_CAPACITY.length(), CapacityAssigner },
422 { BATTERY_KEY_TOTAL_ENERGY.c_str(), BATTERY_KEY_TOTAL_ENERGY.length(), TotalEnergyAssigner },
423 { BATTERY_KEY_REMAIN_ENERGY.c_str(), BATTERY_KEY_REMAIN_ENERGY.length(), RemainEnergyAssigner },
424 { BATTERY_KEY_VOLTAGE.c_str(), BATTERY_KEY_VOLTAGE.length(), VoltageAssigner },
425 { BATTERY_KEY_TEMPERATURE.c_str(), BATTERY_KEY_TEMPERATURE.length(), TemperatureAssigner },
426 { BATTERY_KEY_HEALTH.c_str(), BATTERY_KEY_HEALTH.length(), HealthStateAssigner },
427 { BATTERY_KEY_CHARGE_STATUS.c_str(), BATTERY_KEY_CHARGE_STATUS.length(), ChargeStateAssigner },
428 { BATTERY_KEY_PRESENT.c_str(), BATTERY_KEY_PRESENT.length(), PresentAssigner },
429 { BATTERY_KEY_TECHNOLOGY.c_str(), BATTERY_KEY_TECHNOLOGY.length(), TechnologyAssigner },
430 { BATTERY_KEY_CHARGE_COUNTER.c_str(), BATTERY_KEY_CHARGE_COUNTER.length(), ChargeCounterAssigner },
431 { BATTERY_KEY_CURRENT_AVERAGE.c_str(), BATTERY_KEY_CURRENT_AVERAGE.length(), CurrentAverageAssigner },
432 { BATTERY_KEY_CURRENT_NOW.c_str(), BATTERY_KEY_CURRENT_NOW.length(), CurrentNowAssigner },
433 { nullptr, 0, nullptr } // end of the array
434 };
435
436 while (*msg) {
437 for (int32_t i = 0; batteryAssigners[i].prefix; ++i) {
438 if (!strncmp(msg, batteryAssigners[i].prefix, batteryAssigners[i].prefixLen)) {
439 BATTERY_HILOGD(FEATURE_BATT_INFO, "msg: %{public}s", msg);
440 msg += batteryAssigners[i].prefixLen;
441 batteryAssigners[i].Assigner(msg, info);
442 break;
443 }
444 }
445 while (*msg++) {} // move to next
446 }
447
448 info->pluggedType_ = PLUGGED_TYPE_NONE;
449 ParsePluggedType(&info->pluggedType_);
450
451 info->pluggedMaxCurrent_ = INVALID_BATT_INT_VALUE;
452 ParsePluggedMaxCurrent(&info->pluggedMaxCurrent_);
453
454 info->pluggedMaxVoltage_ = INVALID_BATT_INT_VALUE;
455 ParsePluggedMaxVoltage(&info->pluggedMaxVoltage_);
456
457 info->technology_ = INVALID_STRING_VALUE;
458 ParseTechnology(info->technology_);
459
460 CopyBatteryInfo(info);
461 }
462
CopyBatteryInfo(const struct BatterydInfo * info) const463 void PowerSupplyProvider::CopyBatteryInfo(const struct BatterydInfo* info) const
464 {
465 g_batteryInfo.capacity_ = info->capacity_;
466 g_batteryInfo.voltage_ = info->voltage_;
467 g_batteryInfo.temperature_ = info->temperature_;
468 g_batteryInfo.healthState_ = info->healthState_;
469 g_batteryInfo.pluggedType_ = info->pluggedType_;
470 g_batteryInfo.pluggedMaxCurrent_ = info->pluggedMaxCurrent_;
471 g_batteryInfo.pluggedMaxVoltage_ = info->pluggedMaxVoltage_;
472 g_batteryInfo.chargeState_ = info->chargeState_;
473 g_batteryInfo.chargeCounter_ = info->chargeCounter_;
474 g_batteryInfo.curNow_ = info->curNow_;
475 g_batteryInfo.curAverage_ = info->curAverage_;
476 g_batteryInfo.totalEnergy_ = info->totalEnergy_;
477 g_batteryInfo.remainEnergy_ = info->remainEnergy_;
478 g_batteryInfo.present_ = info->present_;
479 g_batteryInfo.technology_ = info->technology_;
480 }
481
SetSysFilePath(const std::string & path)482 void PowerSupplyProvider::SetSysFilePath(const std::string& path)
483 {
484 if (path.empty()) {
485 BATTERY_HILOGI(FEATURE_BATT_INFO, "path is empty");
486 return;
487 }
488 path_ = path;
489 }
490
CreateFile(const std::string & path,const std::string & content)491 void PowerSupplyProvider::CreateFile(const std::string& path, const std::string& content)
492 {
493 if (access(path.c_str(), F_OK) == 0) {
494 return;
495 }
496
497 std::ofstream stream(path.c_str());
498 if (!stream.is_open()) {
499 BATTERY_HILOGE(FEATURE_BATT_INFO, "cannot create file");
500 return;
501 }
502 stream << content.c_str() << std::endl;
503 stream.close();
504 }
505
InitBatteryPath()506 void PowerSupplyProvider::InitBatteryPath()
507 {
508 std::string sysLowercaseBatteryPath = "/sys/class/power_supply/battery";
509
510 if (access(sysLowercaseBatteryPath.c_str(), F_OK) == 0) {
511 BATTERY_HILOGI(FEATURE_BATT_INFO, "system battery path is exist");
512 return;
513 } else {
514 std::string sysCapitalBatteryPath = "/sys/class/power_supply/Battery";
515 if (access(sysCapitalBatteryPath.c_str(), F_OK) == 0) {
516 BATTERY_HILOGI(FEATURE_BATT_INFO, "system Battery path is exist");
517 return;
518 }
519 InitDefaultSysfs();
520 }
521 }
522
InitPowerSupplySysfs()523 int32_t PowerSupplyProvider::InitPowerSupplySysfs()
524 {
525 DIR* dir = nullptr;
526 struct dirent* entry = nullptr;
527 index_ = 0;
528
529 dir = opendir(path_.c_str());
530 if (dir == nullptr) {
531 BATTERY_HILOGE(FEATURE_BATT_INFO, "cannot open path_");
532 return HDF_ERR_IO;
533 }
534
535 while (true) {
536 entry = readdir(dir);
537 if (entry == nullptr) {
538 break;
539 }
540
541 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
542 continue;
543 }
544
545 if (entry->d_type == DT_DIR || entry->d_type == DT_LNK) {
546 if (index_ >= MAX_SYSFS_SIZE) {
547 BATTERY_HILOGW(FEATURE_BATT_INFO, "too many power supply types");
548 break;
549 }
550 nodeNames_.emplace_back(entry->d_name);
551 index_++;
552 }
553 }
554 struct PowerSupplySysfsInfo sysfsInfo = {};
555 nodeNamePathMap_.clear();
556 TraversalNode();
557 FormatSysfsPaths(&sysfsInfo);
558 BATTERY_HILOGD(FEATURE_BATT_INFO, "init power supply sysfs nodes, total count %{public}d", index_);
559 closedir(dir);
560
561 return HDF_SUCCESS;
562 }
563
TraversalNode()564 void PowerSupplyProvider::TraversalNode()
565 {
566 nodeNamePathMap_.insert(std::make_pair("type", ""));
567 nodeNamePathMap_.insert(std::make_pair("online", ""));
568 nodeNamePathMap_.insert(std::make_pair("current_max", ""));
569 nodeNamePathMap_.insert(std::make_pair("voltage_max", ""));
570 nodeNamePathMap_.insert(std::make_pair("capacity", ""));
571 nodeNamePathMap_.insert(std::make_pair("voltage_now", ""));
572 nodeNamePathMap_.insert(std::make_pair("temp", ""));
573 nodeNamePathMap_.insert(std::make_pair("health", ""));
574 nodeNamePathMap_.insert(std::make_pair("status", ""));
575 nodeNamePathMap_.insert(std::make_pair("present", ""));
576 nodeNamePathMap_.insert(std::make_pair("charge_counter", ""));
577 nodeNamePathMap_.insert(std::make_pair("technology", ""));
578 nodeNamePathMap_.insert(std::make_pair("charge_full", ""));
579 nodeNamePathMap_.insert(std::make_pair("current_avg", ""));
580 nodeNamePathMap_.insert(std::make_pair("current_now", ""));
581 nodeNamePathMap_.insert(std::make_pair("charge_now", ""));
582
583 auto iter = nodeNames_.begin();
584 while (iter != nodeNames_.end()) {
585 if (*iter == "battery") {
586 CheckSubfolderNode(*iter);
587 iter = nodeNames_.erase(iter);
588 } else {
589 iter++;
590 }
591 }
592
593 iter = nodeNames_.begin();
594 while (iter != nodeNames_.end()) {
595 if (*iter == POWER_SUPPLY_BATTERY) {
596 CheckSubfolderNode(*iter);
597 iter = nodeNames_.erase(iter);
598 } else {
599 iter++;
600 }
601 }
602
603 for (auto& nodeName : nodeNames_) {
604 CheckSubfolderNode(nodeName);
605 }
606 }
607
CheckSubfolderNode(const std::string & path)608 void PowerSupplyProvider::CheckSubfolderNode(const std::string& path)
609 {
610 DIR *dir = nullptr;
611 struct dirent* entry = nullptr;
612 std::string batteryPath = path_ + "/" + path;
613
614 dir = opendir(batteryPath.c_str());
615 if (dir == nullptr) {
616 BATTERY_HILOGE(FEATURE_BATT_INFO, "subfolder file is not exist.");
617 return;
618 }
619
620 while (true) {
621 entry = readdir(dir);
622 if (entry == nullptr) {
623 break;
624 }
625
626 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
627 continue;
628 }
629
630 if (entry->d_type == DT_DIR || entry->d_type == DT_LNK) {
631 continue;
632 }
633
634 if ((strcmp(entry->d_name, "type") == 0) && (nodeNamePathMap_["type"].empty()) &&
635 (strcasecmp(path.c_str(), BATTERY_NODE_PATH.c_str()) != 0)) {
636 nodeNamePathMap_["type"] = path;
637 }
638
639 for (auto & iter : nodeNamePathMap_) {
640 if ((strcmp(entry->d_name, iter.first.c_str()) == 0) && (nodeNamePathMap_[iter.first].empty())) {
641 nodeNamePathMap_[iter.first] = path;
642 }
643 }
644 }
645 closedir(dir);
646 }
647
ParseCapacity(int32_t * capacity) const648 int32_t PowerSupplyProvider::ParseCapacity(int32_t* capacity) const
649 {
650 char buf[MAX_BUFF_SIZE] = {0};
651
652 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.capacityPath.c_str(), buf, sizeof(buf));
653 if (ret != HDF_SUCCESS) {
654 return ret;
655 }
656
657 int32_t value = ParseInt(buf);
658 *capacity = value;
659
660 return HDF_SUCCESS;
661 }
662
ParseTotalEnergy(int32_t * totalEnergy) const663 int32_t PowerSupplyProvider::ParseTotalEnergy(int32_t* totalEnergy) const
664 {
665 char buf[MAX_BUFF_SIZE] = {0};
666
667 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.totalEnergyPath.c_str(), buf, sizeof(buf));
668 if (ret != HDF_SUCCESS) {
669 return ret;
670 }
671
672 int32_t value = ParseInt(buf);
673 *totalEnergy = value;
674
675 return HDF_SUCCESS;
676 }
677
ParseCurrentAverage(int32_t * curAverage) const678 int32_t PowerSupplyProvider::ParseCurrentAverage(int32_t* curAverage) const
679 {
680 char buf[MAX_BUFF_SIZE] = {0};
681
682 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.curAveragePath.c_str(), buf, sizeof(buf));
683 if (ret != HDF_SUCCESS) {
684 return ret;
685 }
686
687 int32_t value = ParseInt(buf);
688 *curAverage = value;
689
690 return HDF_SUCCESS;
691 }
692
ParseCurrentNow(int32_t * curNow) const693 int32_t PowerSupplyProvider::ParseCurrentNow(int32_t* curNow) const
694 {
695 char buf[MAX_BUFF_SIZE] = {0};
696
697 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.curNowPath.c_str(), buf, sizeof(buf));
698 if (ret != HDF_SUCCESS) {
699 return ret;
700 }
701
702 int32_t value = ParseInt(buf);
703 *curNow = value;
704
705 return HDF_SUCCESS;
706 }
707
ParseRemainEnergy(int32_t * remainEnergy) const708 int32_t PowerSupplyProvider::ParseRemainEnergy(int32_t* remainEnergy) const
709 {
710 char buf[MAX_BUFF_SIZE] = {0};
711
712 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.remainEnergyPath.c_str(), buf, sizeof(buf));
713 if (ret != HDF_SUCCESS) {
714 return ret;
715 }
716
717 int32_t value = ParseInt(buf);
718 *remainEnergy = value;
719
720 return HDF_SUCCESS;
721 }
722
ParseVoltage(int32_t * voltage) const723 int32_t PowerSupplyProvider::ParseVoltage(int32_t* voltage) const
724 {
725 char buf[MAX_BUFF_SIZE] = {0};
726 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.voltagePath.c_str(), buf, sizeof(buf));
727 if (ret != HDF_SUCCESS) {
728 return ret;
729 }
730
731 int32_t value = ParseInt(buf);
732 *voltage = value;
733
734 return HDF_SUCCESS;
735 }
736
ParseTemperature(int32_t * temperature) const737 int32_t PowerSupplyProvider::ParseTemperature(int32_t* temperature) const
738 {
739 char buf[MAX_BUFF_SIZE] = {0};
740 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.temperaturePath.c_str(), buf, sizeof(buf));
741 if (ret != HDF_SUCCESS) {
742 return ret;
743 }
744
745 int32_t value = ParseInt(buf);
746 *temperature = value;
747
748 return HDF_SUCCESS;
749 }
750
ParseHealthState(int32_t * healthState) const751 int32_t PowerSupplyProvider::ParseHealthState(int32_t* healthState) const
752 {
753 char buf[MAX_BUFF_SIZE] = {0};
754 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.healthStatePath.c_str(), buf, sizeof(buf));
755 if (ret != HDF_SUCCESS) {
756 return ret;
757 }
758
759 Trim(buf);
760 *healthState = HealthStateEnumConverter(buf);
761 return HDF_SUCCESS;
762 }
763
ParsePluggedType(int32_t * pluggedType) const764 int32_t PowerSupplyProvider::ParsePluggedType(int32_t* pluggedType) const
765 {
766 char buf[MAX_BUFF_SIZE] = {0};
767 GetPluggedTypeName(buf, sizeof(buf));
768 int32_t type = PluggedTypeEnumConverter(buf);
769 if (type == PLUGGED_TYPE_BUTT) {
770 BATTERY_HILOGW(FEATURE_BATT_INFO, "not support the online type %{public}s", buf);
771 return HDF_ERR_NOT_SUPPORT;
772 }
773
774 *pluggedType = type;
775 return HDF_SUCCESS;
776 }
777
ParseChargeState(int32_t * chargeState) const778 int32_t PowerSupplyProvider::ParseChargeState(int32_t* chargeState) const
779 {
780 char buf[MAX_BUFF_SIZE] = {0};
781 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.chargeStatePath.c_str(), buf, sizeof(buf));
782 if (ret != HDF_SUCCESS) {
783 return ret;
784 }
785
786 Trim(buf);
787 *chargeState = ChargeStateEnumConverter(buf);
788 return HDF_SUCCESS;
789 }
790
ParsePresent(int8_t * present) const791 int32_t PowerSupplyProvider::ParsePresent(int8_t* present) const
792 {
793 char buf[MAX_BUFF_SIZE] = {0};
794 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.presentPath.c_str(), buf, sizeof(buf));
795 if (ret != HDF_SUCCESS) {
796 return ret;
797 }
798
799 auto value = static_cast<int8_t>(ParseInt(buf));
800 *present = value;
801 return HDF_SUCCESS;
802 }
803
ParseChargeCounter(int32_t * chargeCounter) const804 int32_t PowerSupplyProvider::ParseChargeCounter(int32_t* chargeCounter) const
805 {
806 char buf[MAX_BUFF_SIZE] = {0};
807 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.chargeCounterPath.c_str(), buf, sizeof(buf));
808 if (ret != HDF_SUCCESS) {
809 return ret;
810 }
811
812 int32_t value = ParseInt(buf);
813 *chargeCounter = value;
814
815 return HDF_SUCCESS;
816 }
817
ParseTechnology(std::string & technology) const818 int32_t PowerSupplyProvider::ParseTechnology(std::string& technology) const
819 {
820 char buf[MAX_BUFF_SIZE] = {0};
821 int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.technologyPath.c_str(), buf, sizeof(buf));
822 if (ret != HDF_SUCCESS) {
823 return ret;
824 }
825
826 technology.assign(buf, strlen(buf));
827 return HDF_SUCCESS;
828 }
829
GetBatteryInfo() const830 BatterydInfo PowerSupplyProvider::GetBatteryInfo() const
831 {
832 UpdateInfoByReadSysFile(&g_batteryInfo);
833 return g_batteryInfo;
834 }
835
CreateMockTechPath(std::string & mockTechPath)836 void PowerSupplyProvider::CreateMockTechPath(std::string& mockTechPath)
837 {
838 BATTERY_HILOGI(FEATURE_BATT_INFO, "create mockFilePath path");
839 CreateFile(mockTechPath + "/capacity", "1000");
840 CreateFile(mockTechPath + "/current_avg", "1000");
841 CreateFile(mockTechPath + "/current_now", "1000");
842 CreateFile(mockTechPath + "/health", "Over voltage");
843 CreateFile(mockTechPath + "/present", "0");
844 CreateFile(mockTechPath + "/status", "Not charging");
845 CreateFile(mockTechPath + "/type", "Unknown");
846 CreateFile(mockTechPath + "/temp", "345");
847 CreateFile(mockTechPath + "/technology", "Li-ion");
848 }
849
CreateMockChargerPath(std::string & mockChargerPath)850 void PowerSupplyProvider::CreateMockChargerPath(std::string& mockChargerPath)
851 {
852 BATTERY_HILOGI(FEATURE_BATT_INFO, "create mockFilePath path");
853 CreateFile(mockChargerPath + "/type", "USB");
854 CreateFile(mockChargerPath + "/constant_charge_current", "0");
855 CreateFile(mockChargerPath + "/health", "Good");
856 CreateFile(mockChargerPath + "/online", "1");
857 CreateFile(mockChargerPath + "/status", "Charging");
858 CreateFile(mockChargerPath + "/type", "USB");
859 }
860
CreateMockBatteryPath(std::string & mockBatteryPath)861 void PowerSupplyProvider::CreateMockBatteryPath(std::string& mockBatteryPath)
862 {
863 BATTERY_HILOGI(FEATURE_BATT_INFO, "create mockFilePath path");
864 CreateFile(mockBatteryPath + "/capacity", "11");
865 CreateFile(mockBatteryPath + "/charge_control_limit", "0");
866 CreateFile(mockBatteryPath + "/charge_counter", "4000000");
867 CreateFile(mockBatteryPath + "/charge_full", "4000000");
868 CreateFile(mockBatteryPath + "/charge_now", "4000000");
869 CreateFile(mockBatteryPath + "/constant_charge_current", "0");
870 CreateFile(mockBatteryPath + "/current_avg", "1000");
871 CreateFile(mockBatteryPath + "/current_now", "1000");
872 CreateFile(mockBatteryPath + "/health", "Good");
873 CreateFile(mockBatteryPath + "/input_current_limit", "0");
874 CreateFile(mockBatteryPath + "/online", "1");
875 CreateFile(mockBatteryPath + "/present", "0");
876 CreateFile(mockBatteryPath + "/status", "Full");
877 CreateFile(mockBatteryPath + "/temp", "222");
878 CreateFile(mockBatteryPath + "/voltage_avg", "4123456");
879 CreateFile(mockBatteryPath + "/voltage_now", "4123456");
880 CreateFile(mockBatteryPath + "/type", "Battery");
881 }
882
InitDefaultSysfs()883 void PowerSupplyProvider::InitDefaultSysfs()
884 {
885 std::string mockBatteryPath = MOCK_POWER_SUPPLY_BASE_PATH + "/battery";
886 std::string mockChargerPath = MOCK_POWER_SUPPLY_BASE_PATH + "/ohos_charger";
887 std::string mockTechPath = MOCK_POWER_SUPPLY_BASE_PATH + "/ohos-fgu";
888
889 if (access(mockBatteryPath.c_str(), 0) == -1) {
890 mkdir(mockBatteryPath.c_str(), S_IRWXU | S_IRWXG);
891 sleep(MKDIR_WAIT_TIME);
892 }
893
894 if (access(mockChargerPath.c_str(), 0) == -1) {
895 mkdir(mockChargerPath.c_str(), S_IRWXU);
896 sleep(MKDIR_WAIT_TIME);
897 }
898
899 if (access(mockTechPath.c_str(), 0) == -1) {
900 mkdir(mockTechPath.c_str(), S_IRWXU);
901 sleep(MKDIR_WAIT_TIME);
902 }
903
904 CreateMockTechPath(mockTechPath);
905 CreateMockChargerPath(mockChargerPath);
906 CreateMockBatteryPath(mockBatteryPath);
907 path_ = MOCK_POWER_SUPPLY_BASE_PATH;
908 }
909
SetChargingLimit(const std::vector<ChargingLimit> & chargerLimitList,std::string & currentPath,std::string & voltagePath)910 int32_t PowerSupplyProvider::SetChargingLimit(const std::vector<ChargingLimit>& chargerLimitList,
911 std::string& currentPath, std::string& voltagePath)
912 {
913 BATTERY_HILOGD(FEATURE_BATT_INFO, "enter");
914 if (chargerLimitList.empty()) {
915 BATTERY_HILOGE(FEATURE_BATT_INFO, "the parameter is empty");
916 return HDF_ERR_INVALID_PARAM;
917 }
918
919 std::string limitPath;
920 std::string chargeLimitStr;
921 for (const auto& iter : chargerLimitList) {
922 if (iter.type == ChargingLimitType::TYPE_CURRENT) {
923 limitPath = currentPath;
924 } else if (iter.type == ChargingLimitType::TYPE_VOLTAGE) {
925 limitPath = voltagePath;
926 }
927 chargeLimitStr = chargeLimitStr + (iter.protocol + " " + std::to_string(iter.value) + "\n");
928 }
929 int32_t ret = WriteChargingLimit(limitPath, chargeLimitStr);
930 if (ret < HDF_SUCCESS) {
931 return ret;
932 }
933 BATTERY_HILOGI(FEATURE_BATT_INFO, "Exit");
934 return HDF_SUCCESS;
935 }
936
WriteChargingLimit(std::string chargingLimitPath,std::string & str)937 int32_t PowerSupplyProvider::WriteChargingLimit(std::string chargingLimitPath, std::string& str)
938 {
939 BATTERY_HILOGI(FEATURE_BATT_INFO, "Enter");
940 std::fstream out(chargingLimitPath, std::ios::out | std::ios::trunc);
941 out << str;
942 out.close();
943 BATTERY_HILOGI(FEATURE_BATT_INFO, "Exit");
944 return HDF_SUCCESS;
945 }
946 } // namespace V1_1
947 } // namespace Battery
948 } // namespace HDI
949 } // namespace OHOS
950