• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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