• 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 <iostream>
21 #include <securec.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25 #include "osal/osal_mem.h"
26 #include "utils/hdf_log.h"
27 
28 #define HDF_LOG_TAG PowerSupplyProvider
29 
30 namespace OHOS {
31 namespace HDI {
32 namespace Battery {
33 namespace V1_0 {
34 const int MAX_BUFF_SIZE = 128;
35 const int INVALID_BATT_INT_VALUE = -1;
36 const int STR_TO_LONG_LEN = 10;
37 const int UVOL_TO_MVOL = 1000;
38 const int MKDIR_WAIT_TIME = 1;
39 const int NUM_ZERO = 0;
40 const std::string POWER_SUPPLY_BASE_PATH = "/sys/class/power_supply";
41 const std::string POWER_SUPPLY_BATTERY = "Battery";
42 const std::string BATTERY_KEY_CAPACITY = "POWER_SUPPLY_CAPACITY=";
43 const std::string BATTERY_KEY_VOLTAGE = "POWER_SUPPLY_VOLTAGE_NOW=";
44 const std::string BATTERY_KEY_TEMPERATURE = "POWER_SUPPLY_TEMP=";
45 const std::string BATTERY_KEY_HEALTH = "POWER_SUPPLY_HEALTH=";
46 const std::string BATTERY_KEY_CHARGE_STATUS = "POWER_SUPPLY_STATUS=";
47 const std::string BATTERY_KEY_PRESENT = "POWER_SUPPLY_PRESENT=";
48 const std::string BATTERY_KEY_TECHNOLOGY = "POWER_SUPPLY_TECHNOLOGY=";
49 const std::string BATTERY_KEY_CHARGE_COUNTER = "POWER_SUPPLY_CHARGE_COUNTER=";
50 const std::string BATTERY_KEY_TOTAL_ENERGY = "POWER_SUPPLY_TOTAL_ENERGY=";
51 const std::string BATTERY_KEY_REMAIN_ENERGY = "POWER_SUPPLY_REMAIN_ENERGY=";
52 const std::string BATTERY_KEY_CURRENT_AVERAGE = "POWER_SUPPLY_CURRENT_AVERAGE=";
53 const std::string BATTERY_KEY_CURRENT_NOW = "POWER_SUPPLY_CURRENT_NOW=";
54 const std::string INVALID_STRING_VALUE = "invalid";
55 const std::string BATTERY_NODE_PATH = "battery";
56 const std::string CHARGER_NODE_PATH = "ohos_charger";
57 const std::string FGU_NODE_PATH = "ohos-fgu";
58 BatterydInfo g_batteryInfo;
59 
60 struct StringEnumMap {
61     const char* str;
62     int32_t enumVal;
63 };
64 
65 struct BatteryAssigner {
66     const char* prefix;
67     const size_t prefixLen;
68     void (*Assigner)(const char*, struct BatterydInfo*);
69 };
70 
PowerSupplyProvider()71 PowerSupplyProvider::PowerSupplyProvider()
72 {
73     path_ = POWER_SUPPLY_BASE_PATH;
74 }
75 
ParseInt(const char * str)76 inline int32_t PowerSupplyProvider::ParseInt(const char* str)
77 {
78     return strtol(str, nullptr, STR_TO_LONG_LEN);
79 }
80 
Trim(char * str) const81 inline void PowerSupplyProvider::Trim(char* str) const
82 {
83     if (str == nullptr) {
84         return;
85     }
86 
87     str[strcspn(str, "\n")] = 0;
88 }
89 
CapacityAssigner(const char * str,struct BatterydInfo * info)90 inline void PowerSupplyProvider::CapacityAssigner(const char* str, struct BatterydInfo* info)
91 {
92     info->capacity_ = ParseInt(str); // default in percent format
93 }
94 
TotalEnergyAssigner(const char * str,struct BatterydInfo * info)95 inline void PowerSupplyProvider::TotalEnergyAssigner(const char* str, struct BatterydInfo* info)
96 {
97     info->totalEnergy_ = ParseInt(str);
98 }
99 
RemainEnergyAssigner(const char * str,struct BatterydInfo * info)100 inline void PowerSupplyProvider::RemainEnergyAssigner(const char* str, struct BatterydInfo* info)
101 {
102     info->remainEnergy_ = ParseInt(str);
103 }
104 
VoltageAssigner(const char * str,struct BatterydInfo * info)105 inline void PowerSupplyProvider::VoltageAssigner(const char* str, struct BatterydInfo* info)
106 {
107     info->voltage_ = ParseInt(str) / UVOL_TO_MVOL; // convert to millivolt(mV) format
108 }
109 
TemperatureAssigner(const char * str,struct BatterydInfo * info)110 inline void PowerSupplyProvider::TemperatureAssigner(const char* str, struct BatterydInfo* info)
111 {
112     info->temperature_ = ParseInt(str);
113 }
114 
HealthStateEnumConverter(const char * str)115 int32_t PowerSupplyProvider::HealthStateEnumConverter(const char* str)
116 {
117     struct StringEnumMap healthStateEnumMap[] = {
118         { "Good", BATTERY_HEALTH_GOOD },
119         { "Cold", BATTERY_HEALTH_COLD },
120         { "Warm", BATTERY_HEALTH_GOOD }, // JEITA specification
121         { "Cool", BATTERY_HEALTH_GOOD }, // JEITA specification
122         { "Hot", BATTERY_HEALTH_OVERHEAT }, // JEITA specification
123         { "Overheat", BATTERY_HEALTH_OVERHEAT },
124         { "Over voltage", BATTERY_HEALTH_OVERVOLTAGE },
125         { "Dead", BATTERY_HEALTH_DEAD },
126         { "Unknown", BATTERY_HEALTH_UNKNOWN },
127         { "Unspecified failure", BATTERY_HEALTH_UNKNOWN },
128         { NULL, BATTERY_HEALTH_UNKNOWN },
129     };
130 
131     for (int i = 0; healthStateEnumMap[i].str; ++i) {
132         if (strcmp(str, healthStateEnumMap[i].str) == 0) {
133             return healthStateEnumMap[i].enumVal;
134         }
135     }
136 
137     return BATTERY_HEALTH_UNKNOWN;
138 }
139 
HealthStateAssigner(const char * str,struct BatterydInfo * info)140 inline void PowerSupplyProvider::HealthStateAssigner(const char* str, struct BatterydInfo* info)
141 {
142     info->healthState_ = HealthStateEnumConverter(str);
143 }
144 
ChargeStateEnumConverter(const char * str)145 int32_t PowerSupplyProvider::ChargeStateEnumConverter(const char* str)
146 {
147     struct StringEnumMap chargeStateEnumMap[] = {
148         { "Discharging", CHARGE_STATE_NONE },
149         { "Charging", CHARGE_STATE_ENABLE },
150         { "Full", CHARGE_STATE_FULL },
151         { "Not charging", CHARGE_STATE_DISABLE },
152         { "Unknown", CHARGE_STATE_RESERVED },
153         { NULL, CHARGE_STATE_RESERVED },
154     };
155 
156     for (int i = 0; chargeStateEnumMap[i].str; ++i) {
157         if (strcmp(str, chargeStateEnumMap[i].str) == 0) {
158             return chargeStateEnumMap[i].enumVal;
159         }
160     }
161 
162     return CHARGE_STATE_RESERVED;
163 }
164 
ChargeStateAssigner(const char * str,struct BatterydInfo * info)165 inline void PowerSupplyProvider::ChargeStateAssigner(const char* str, struct BatterydInfo* info)
166 {
167     info->chargeState_ = ChargeStateEnumConverter(str);
168 }
169 
PresentAssigner(const char * str,struct BatterydInfo * info)170 inline void PowerSupplyProvider::PresentAssigner(const char* str, struct BatterydInfo* info)
171 {
172     info->present_ = ParseInt(str);
173 }
174 
TechnologyAssigner(const char * str,struct BatterydInfo * info)175 inline void PowerSupplyProvider::TechnologyAssigner(const char* str, struct BatterydInfo* info)
176 {
177     info->technology_ = str;
178 }
179 
ChargeCounterAssigner(const char * str,struct BatterydInfo * info)180 inline void PowerSupplyProvider::ChargeCounterAssigner(const char* str, struct BatterydInfo* info)
181 {
182     info->chargeCounter_ = ParseInt(str);
183 }
184 
CurrentAverageAssigner(const char * str,struct BatterydInfo * info)185 inline void PowerSupplyProvider::CurrentAverageAssigner(const char* str, struct BatterydInfo* info)
186 {
187     info->curAverage_ = ParseInt(str);
188 }
189 
CurrentNowAssigner(const char * str,struct BatterydInfo * info)190 inline void PowerSupplyProvider::CurrentNowAssigner(const char* str, struct BatterydInfo* info)
191 {
192     info->curNow_ = ParseInt(str);
193 }
194 
FormatPath(std::string & path,size_t size,const char * format,const char * basePath,const char * name) const195 void PowerSupplyProvider::FormatPath(std::string& path,
196     size_t size, const char* format, const char* basePath, const char* name) const
197 {
198     char buff[PATH_MAX] = {0};
199     if (strcpy_s(buff, PATH_MAX, path.c_str()) != EOK) {
200         HDF_LOGW("%{public}s: failed to copy path of %{public}s", __func__, name);
201         return;
202     }
203 
204     if (snprintf_s(buff, PATH_MAX, size - 1, format, basePath, name) == -1) {
205         HDF_LOGW("%{public}s: failed to format path of %{public}s", __func__, name);
206         return;
207     }
208     path.assign(buff, strlen(buff));
209     HDF_LOGI("%{public}s: path is %{public}s", __func__, path.c_str());
210 
211     return;
212 }
213 
FormatSysfsPaths(struct PowerSupplySysfsInfo * info)214 void PowerSupplyProvider::FormatSysfsPaths(struct PowerSupplySysfsInfo* info)
215 {
216     // Format paths for power supply types
217     FormatPath(info->typePath, PATH_MAX, "%s/%s/type",
218         path_.c_str(), nodeInfo_["type"].c_str());
219     FormatPath(info->onlinePath, PATH_MAX, "%s/%s/online",
220         path_.c_str(), nodeInfo_["online"].c_str());
221     FormatPath(info->currentMaxPath, PATH_MAX, "%s/%s/current_max",
222         path_.c_str(), nodeInfo_["current_max"].c_str());
223     FormatPath(info->voltageMaxPath, PATH_MAX, "%s/%s/voltage_max",
224         path_.c_str(), nodeInfo_["voltage_max"].c_str());
225 
226     FormatPath(batterySysfsInfo_.capacityPath, PATH_MAX,
227         "%s/%s/capacity", path_.c_str(), nodeInfo_["capacity"].c_str());
228     FormatPath(batterySysfsInfo_.voltagePath, PATH_MAX,
229         "%s/%s/voltage_now", path_.c_str(), nodeInfo_["voltage_now"].c_str());
230     FormatPath(batterySysfsInfo_.temperaturePath, PATH_MAX,
231         "%s/%s/temp", path_.c_str(), nodeInfo_["temp"].c_str());
232     FormatPath(batterySysfsInfo_.healthStatePath, PATH_MAX,
233         "%s/%s/health", path_.c_str(), nodeInfo_["health"].c_str());
234     FormatPath(batterySysfsInfo_.chargeStatePath, PATH_MAX,
235         "%s/%s/status", path_.c_str(), nodeInfo_["status"].c_str());
236     FormatPath(batterySysfsInfo_.presentPath, PATH_MAX,
237         "%s/%s/present", path_.c_str(), nodeInfo_["present"].c_str());
238     FormatPath(batterySysfsInfo_.chargeCounterPath, PATH_MAX,
239         "%s/%s/charge_counter", path_.c_str(), nodeInfo_["charge_counter"].c_str());
240     FormatPath(batterySysfsInfo_.technologyPath, PATH_MAX,
241         "%s/%s/technology", path_.c_str(), nodeInfo_["technology"].c_str());
242     FormatPath(batterySysfsInfo_.totalEnergyPath, PATH_MAX,
243         "%s/%s/charge_full", path_.c_str(), nodeInfo_["charge_full"].c_str());
244     FormatPath(batterySysfsInfo_.curAveragePath, PATH_MAX,
245         "%s/%s/current_avg", path_.c_str(), nodeInfo_["current_avg"].c_str());
246     FormatPath(batterySysfsInfo_.curNowPath, PATH_MAX,
247         "%s/%s/current_now", path_.c_str(), nodeInfo_["current_now"].c_str());
248     FormatPath(batterySysfsInfo_.remainEnergyPath, PATH_MAX,
249         "%s/%s/charge_now", path_.c_str(), nodeInfo_["charge_now"].c_str());
250 
251     return;
252 }
253 
ReadSysfsFile(const char * path,char * buf,size_t size) const254 int32_t PowerSupplyProvider::ReadSysfsFile(const char* path, char* buf, size_t size) const
255 {
256     int32_t readSize;
257     int fd = open(path, O_RDONLY);
258     if (fd < NUM_ZERO) {
259         HDF_LOGE("%{public}s: failed to open %{public}s", __func__, path);
260         return HDF_ERR_IO;
261     }
262 
263     readSize = read(fd, buf, size - 1);
264     if (readSize < NUM_ZERO) {
265         HDF_LOGE("%{public}s: failed to read %{public}s", __func__, path);
266         close(fd);
267         return HDF_ERR_IO;
268     }
269 
270     buf[readSize] = '\0';
271     Trim(buf);
272     close(fd);
273 
274     return HDF_SUCCESS;
275 }
276 
ReadBatterySysfsToBuff(const char * path,char * buf,size_t size) const277 int32_t PowerSupplyProvider::ReadBatterySysfsToBuff(const char* path, char* buf, size_t size) const
278 {
279     int32_t ret = ReadSysfsFile(path, buf, size);
280     if (ret != HDF_SUCCESS) {
281         HDF_LOGW("%{public}s: read path %{private}s failed, ret: %{public}d", __func__, path, ret);
282         return ret;
283     }
284 
285     return HDF_SUCCESS;
286 }
287 
GetPluggedTypeName(char * buf,size_t size) const288 void PowerSupplyProvider::GetPluggedTypeName(char* buf, size_t size) const
289 {
290     std::string onlineNode = "USB";
291     int32_t ret;
292     int32_t online;
293     std::string onlinePath;
294 
295     auto iter = filenodeName_.begin();
296     while (iter != filenodeName_.end()) {
297         onlinePath = path_ + "/" + *iter + "/" + "online";
298         ret = ReadSysfsFile(onlinePath.c_str(), buf, size);
299         if (ret != HDF_SUCCESS) {
300             HDF_LOGW("%{public}s: read online path failed in loop, ret: %{public}d", __func__, ret);
301         }
302         online = ParseInt(buf);
303         if (online) {
304             onlineNode = *iter;
305             break;
306         }
307         iter++;
308     }
309 
310     HDF_LOGI("%{public}s: online path is: %{public}s", __func__, onlinePath.c_str());
311     ret = ReadSysfsFile(onlinePath.c_str(), buf, size);
312     if (ret != HDF_SUCCESS) {
313         HDF_LOGW("%{public}s: read online path failed, ret: %{public}d", __func__, ret);
314         return;
315     }
316 
317     online = ParseInt(buf);
318     if (!online) {
319         HDF_LOGW("%{public}s: charger is not online, so no type return.", __func__);
320         return;
321     }
322 
323     std::string typeNode = onlineNode;
324     std::string typePath = path_ + "/" + typeNode + "/" + "type";
325     HDF_LOGI("%{public}s: type path is: %{public}s", __func__, typePath.c_str());
326     ret = ReadSysfsFile(typePath.c_str(), buf, size);
327     if (ret != HDF_SUCCESS) {
328         HDF_LOGW("%{public}s: read type path failed, ret: %{public}d", __func__, ret);
329         return;
330     }
331     Trim(buf);
332 
333     return;
334 }
335 
PluggedTypeEnumConverter(const char * str) const336 int32_t PowerSupplyProvider::PluggedTypeEnumConverter(const char* str) const
337 {
338     struct StringEnumMap pluggedTypeEnumMap[] = {
339         { "USB", PLUGGED_TYPE_USB },
340         { "USB_PD_DRP", PLUGGED_TYPE_USB },
341         { "Wireless", PLUGGED_TYPE_WIRELESS },
342         { "Mains", PLUGGED_TYPE_AC },
343         { "UPS", PLUGGED_TYPE_AC },
344         { "USB_ACA", PLUGGED_TYPE_AC },
345         { "USB_C", PLUGGED_TYPE_AC },
346         { "USB_CDP", PLUGGED_TYPE_AC },
347         { "USB_DCP", PLUGGED_TYPE_AC },
348         { "USB_HVDCP", PLUGGED_TYPE_AC },
349         { "USB_PD", PLUGGED_TYPE_AC },
350         { "Unknown", PLUGGED_TYPE_BUTT },
351         { NULL, PLUGGED_TYPE_BUTT },
352     };
353 
354     for (int i = 0; pluggedTypeEnumMap[i].str; ++i) {
355         if (strcmp(str, pluggedTypeEnumMap[i].str) == 0) {
356             return pluggedTypeEnumMap[i].enumVal;
357         }
358     }
359     return PLUGGED_TYPE_BUTT;
360 }
361 
ParsePluggedMaxCurrent(int32_t * maxCurrent) const362 int32_t PowerSupplyProvider::ParsePluggedMaxCurrent(int32_t* maxCurrent) const
363 {
364     char buf[MAX_BUFF_SIZE] = {0};
365     GetPluggedTypeName(buf, sizeof(buf));
366     std::string currentMaxNode = "Battery";
367     for (auto iter = nodeInfo_.begin(); iter != nodeInfo_.end(); ++iter) {
368         if (iter->first == "current_max") {
369             currentMaxNode = iter->second;
370             break;
371         }
372     }
373     std::string currentMaxPath = POWER_SUPPLY_BASE_PATH + "/" + currentMaxNode + "/" + "current_max";
374     int32_t ret = ReadBatterySysfsToBuff(currentMaxPath.c_str(), buf, sizeof(buf));
375     if (ret != HDF_SUCCESS) {
376         return ret;
377     }
378     int32_t value = ParseInt(buf);
379     *maxCurrent = value;
380 
381     return HDF_SUCCESS;
382 }
383 
ParsePluggedMaxVoltage(int32_t * maxVoltage) const384 int32_t PowerSupplyProvider::ParsePluggedMaxVoltage(int32_t* maxVoltage) const
385 {
386     char buf[MAX_BUFF_SIZE] = {0};
387     GetPluggedTypeName(buf, sizeof(buf));
388     std::string voltageMaxNode = "Battery";
389     for (auto iter = nodeInfo_.begin(); iter != nodeInfo_.end(); ++iter) {
390         if (iter->first == "voltage_max") {
391             voltageMaxNode = iter->second;
392             break;
393         }
394     }
395     std::string voltageMaxPath = POWER_SUPPLY_BASE_PATH + "/" + voltageMaxNode + "/" + "voltage_max";
396     int32_t ret = ReadBatterySysfsToBuff(voltageMaxPath.c_str(), buf, sizeof(buf));
397     if (ret != HDF_SUCCESS) {
398         return ret;
399     }
400     int32_t value = ParseInt(buf);
401     *maxVoltage = value;
402 
403     return HDF_SUCCESS;
404 }
405 
UpdateInfoByReadSysFile(struct BatterydInfo * info) const406 void PowerSupplyProvider::UpdateInfoByReadSysFile(struct BatterydInfo* info) const
407 {
408     ParseCapacity(&info->capacity_);
409     ParseVoltage(&info->voltage_);
410     ParseTemperature(&info->temperature_);
411     ParseHealthState(&info->healthState_);
412     ParseChargeState(&info->chargeState_);
413     ParseChargeCounter(&info->chargeCounter_);
414     ParsePresent(&info->present_);
415 
416     info->pluggedType_ = PLUGGED_TYPE_NONE;
417     ParsePluggedType(&info->pluggedType_);
418 
419     info->pluggedMaxCurrent_ = INVALID_BATT_INT_VALUE;
420     ParsePluggedMaxCurrent(&info->pluggedMaxCurrent_);
421 
422     info->pluggedMaxVoltage_ = INVALID_BATT_INT_VALUE;
423     ParsePluggedMaxVoltage(&info->pluggedMaxVoltage_);
424 
425     info->technology_ = INVALID_STRING_VALUE;
426     ParseTechnology(info->technology_);
427 
428     CopyBatteryInfo(info);
429     return;
430 }
431 
ParseUeventToBatterydInfo(const char * msg,struct BatterydInfo * info) const432 void PowerSupplyProvider::ParseUeventToBatterydInfo(const char* msg, struct BatterydInfo* info) const
433 {
434     static struct BatteryAssigner batteryAssigners[] = {
435         { BATTERY_KEY_CAPACITY.c_str(), BATTERY_KEY_CAPACITY.length(), CapacityAssigner },
436         { BATTERY_KEY_TOTAL_ENERGY.c_str(), BATTERY_KEY_TOTAL_ENERGY.length(), TotalEnergyAssigner },
437         { BATTERY_KEY_REMAIN_ENERGY.c_str(), BATTERY_KEY_REMAIN_ENERGY.length(), RemainEnergyAssigner },
438         { BATTERY_KEY_VOLTAGE.c_str(), BATTERY_KEY_VOLTAGE.length(), VoltageAssigner },
439         { BATTERY_KEY_TEMPERATURE.c_str(), BATTERY_KEY_TEMPERATURE.length(), TemperatureAssigner },
440         { BATTERY_KEY_HEALTH.c_str(), BATTERY_KEY_HEALTH.length(), HealthStateAssigner },
441         { BATTERY_KEY_CHARGE_STATUS.c_str(), BATTERY_KEY_CHARGE_STATUS.length(), ChargeStateAssigner },
442         { BATTERY_KEY_PRESENT.c_str(), BATTERY_KEY_PRESENT.length(), PresentAssigner },
443         { BATTERY_KEY_TECHNOLOGY.c_str(), BATTERY_KEY_TECHNOLOGY.length(), TechnologyAssigner },
444         { BATTERY_KEY_CHARGE_COUNTER.c_str(), BATTERY_KEY_CHARGE_COUNTER.length(), ChargeCounterAssigner },
445         { BATTERY_KEY_CURRENT_AVERAGE.c_str(), BATTERY_KEY_CURRENT_AVERAGE.length(), CurrentAverageAssigner },
446         { BATTERY_KEY_CURRENT_NOW.c_str(), BATTERY_KEY_CURRENT_NOW.length(), CurrentNowAssigner },
447         { NULL, 0, NULL } // end of the array
448     };
449 
450     while (*msg) {
451         for (int i = 0; batteryAssigners[i].prefix; ++i) {
452             if (!strncmp(msg, batteryAssigners[i].prefix, batteryAssigners[i].prefixLen)) {
453                 msg += batteryAssigners[i].prefixLen;
454                 batteryAssigners[i].Assigner(msg, info);
455                 break;
456             }
457         }
458         while (*msg++) {} // move to next
459     }
460 
461     info->pluggedType_ = PLUGGED_TYPE_NONE;
462     ParsePluggedType(&info->pluggedType_);
463 
464     info->pluggedMaxCurrent_ = INVALID_BATT_INT_VALUE;
465     ParsePluggedMaxCurrent(&info->pluggedMaxCurrent_);
466 
467     info->pluggedMaxVoltage_ = INVALID_BATT_INT_VALUE;
468     ParsePluggedMaxVoltage(&info->pluggedMaxVoltage_);
469 
470     info->technology_ = INVALID_STRING_VALUE;
471     ParseTechnology(info->technology_);
472 
473     CopyBatteryInfo(info);
474     return;
475 }
476 
CopyBatteryInfo(const struct BatterydInfo * info) const477 void PowerSupplyProvider::CopyBatteryInfo(const struct BatterydInfo* info) const
478 {
479     g_batteryInfo.capacity_ = info->capacity_;
480     g_batteryInfo.voltage_ = info->voltage_;
481     g_batteryInfo.temperature_ = info->temperature_;
482     g_batteryInfo.healthState_ = info->healthState_;
483     g_batteryInfo.pluggedType_ = info->pluggedType_;
484     g_batteryInfo.pluggedMaxCurrent_ = info->pluggedMaxCurrent_;
485     g_batteryInfo.pluggedMaxVoltage_ = info->pluggedMaxVoltage_;
486     g_batteryInfo.chargeState_ = info->chargeState_;
487     g_batteryInfo.chargeCounter_ = info->chargeCounter_;
488     g_batteryInfo.present_ = info->present_;
489     g_batteryInfo.technology_ = info->technology_;
490 }
491 
SetSysFilePath(const std::string & path)492 void PowerSupplyProvider::SetSysFilePath(const std::string& path)
493 {
494     if (path == "") {
495         HDF_LOGI("%{public}s path is empty", __func__);
496         path_ = "/data/local/tmp";
497         return;
498     }
499     path_ = path;
500 }
501 
CreateFile(std::string path,std::string content)502 std::string PowerSupplyProvider::CreateFile(std::string path, std::string content)
503 {
504     std::ofstream stream(path.c_str());
505     if (!stream.is_open()) {
506         HDF_LOGE("%{public}s: Cannot create file %{public}s", __func__, path.c_str());
507         return nullptr;
508     }
509     stream << content.c_str() << std::endl;
510     stream.close();
511     return path;
512 }
513 
InitBatteryPath()514 void PowerSupplyProvider::InitBatteryPath()
515 {
516     std::string sysLowercaseBatteryPath = "/sys/class/power_supply/battery";
517     std::string sysCapitalBatteryPath = "/sys/class/power_supply/Battery";
518 
519     if (access(sysLowercaseBatteryPath.c_str(), F_OK) == 0) {
520         HDF_LOGI("%{public}s: system battery path is exist", __func__);
521         return;
522     } else {
523         if (access(sysCapitalBatteryPath.c_str(), F_OK) == 0) {
524             HDF_LOGI("%{public}s: system Battery path is exist", __func__);
525             return;
526         }
527         InitDefaultSysfs();
528     }
529     return;
530 }
531 
InitPowerSupplySysfs(void)532 int32_t PowerSupplyProvider::InitPowerSupplySysfs(void)
533 {
534     DIR* dir = nullptr;
535     struct dirent* entry = nullptr;
536     index_ = 0;
537 
538     HDF_LOGI("%{public}s: path_ is %{public}s", __func__, path_.c_str());
539     dir = opendir(path_.c_str());
540     if (dir == nullptr) {
541         HDF_LOGE("%{public}s: cannot open POWER_SUPPLY_BASE_PATH", __func__);
542         return HDF_ERR_IO;
543     }
544 
545     while (true) {
546         entry = readdir(dir);
547         if (entry == nullptr) {
548             break;
549         }
550 
551         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
552             continue;
553         }
554 
555         if (entry->d_type == DT_DIR || entry->d_type == DT_LNK) {
556             if (index_ >= MAX_SYSFS_SIZE) {
557                 HDF_LOGE("%{public}s: too many plugged types", __func__);
558                 break;
559             }
560             filenodeName_.emplace_back(entry->d_name);
561             index_++;
562         }
563     }
564     struct PowerSupplySysfsInfo sysfsInfo = {0};
565     nodeInfo_.clear();
566     TraversalNode();
567     FormatSysfsPaths(&sysfsInfo);
568     HDF_LOGD("%{public}s: index_ is %{public}d", __func__, index_);
569     closedir(dir);
570 
571     return HDF_SUCCESS;
572 }
573 
TraversalNode()574 void PowerSupplyProvider::TraversalNode()
575 {
576     nodeInfo_.insert(std::make_pair("type", ""));
577     nodeInfo_.insert(std::make_pair("online", ""));
578     nodeInfo_.insert(std::make_pair("current_max", ""));
579     nodeInfo_.insert(std::make_pair("voltage_max", ""));
580     nodeInfo_.insert(std::make_pair("capacity", ""));
581     nodeInfo_.insert(std::make_pair("voltage_now", ""));
582     nodeInfo_.insert(std::make_pair("temp", ""));
583     nodeInfo_.insert(std::make_pair("health", ""));
584     nodeInfo_.insert(std::make_pair("status", ""));
585     nodeInfo_.insert(std::make_pair("present", ""));
586     nodeInfo_.insert(std::make_pair("charge_counter", ""));
587     nodeInfo_.insert(std::make_pair("technology", ""));
588     nodeInfo_.insert(std::make_pair("charge_full", ""));
589     nodeInfo_.insert(std::make_pair("current_avg", ""));
590     nodeInfo_.insert(std::make_pair("current_now", ""));
591     nodeInfo_.insert(std::make_pair("charge_now", ""));
592 
593     auto iter = filenodeName_.begin();
594     while (iter != filenodeName_.end()) {
595         if (*iter == "battery") {
596             CheckSubfolderNode(*iter);
597             iter = filenodeName_.erase(iter);
598         } else {
599             iter++;
600         }
601     }
602 
603     iter = filenodeName_.begin();
604     while (iter != filenodeName_.end()) {
605         if (*iter == "Battery") {
606             CheckSubfolderNode(*iter);
607             iter = filenodeName_.erase(iter);
608         } else {
609             iter++;
610         }
611     }
612 
613     for (auto it = filenodeName_.begin(); it != filenodeName_.end(); ++it) {
614         CheckSubfolderNode(*it);
615     }
616 }
617 
CheckSubfolderNode(const std::string & path)618 void PowerSupplyProvider::CheckSubfolderNode(const std::string& path)
619 {
620     DIR *dir = nullptr;
621     struct dirent* entry = nullptr;
622     std::string batteryPath = path_ + "/" + path;
623     HDF_LOGI("%{public}s: subfolder path is:%{public}s", __func__, batteryPath.c_str());
624 
625     dir = opendir(batteryPath.c_str());
626     if (dir == nullptr) {
627         HDF_LOGE("%{public}s: subfolder file is not exist.", __func__);
628         return;
629     }
630 
631     while (true) {
632         entry = readdir(dir);
633         if (entry == nullptr) {
634             break;
635         }
636 
637         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
638             continue;
639         }
640 
641         if (entry->d_type == DT_DIR || entry->d_type == DT_LNK) {
642             continue;
643         }
644 
645         if ((strcmp(entry->d_name, "type") == 0) && (nodeInfo_["type"] == "") &&
646             (strcasecmp(path.c_str(), BATTERY_NODE_PATH.c_str()) != 0)) {
647             nodeInfo_["type"] = path;
648         }
649 
650         for (auto iter = nodeInfo_.begin(); iter != nodeInfo_.end(); ++iter) {
651             if ((strcmp(entry->d_name, iter->first.c_str()) == 0) && (nodeInfo_[iter->first] == "")) {
652                 nodeInfo_[iter->first] = path;
653             }
654         }
655     }
656     closedir(dir);
657 }
658 
ParseCapacity(int32_t * capacity) const659 int32_t PowerSupplyProvider::ParseCapacity(int32_t* capacity) const
660 {
661     char buf[MAX_BUFF_SIZE] = {0};
662 
663     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.capacityPath.c_str(), buf, sizeof(buf));
664     if (ret != HDF_SUCCESS) {
665         return ret;
666     }
667 
668     int32_t value = ParseInt(buf);
669     *capacity = value;
670 
671     return HDF_SUCCESS;
672 }
673 
ParseTotalEnergy(int32_t * totalEnergy) const674 int32_t PowerSupplyProvider::ParseTotalEnergy(int32_t* totalEnergy) const
675 {
676     char buf[MAX_BUFF_SIZE] = {0};
677 
678     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.totalEnergyPath.c_str(), buf, sizeof(buf));
679     if (ret != HDF_SUCCESS) {
680         return ret;
681     }
682 
683     int32_t value = ParseInt(buf);
684     *totalEnergy = value;
685 
686     return HDF_SUCCESS;
687 }
688 
ParseCurrentAverage(int32_t * curAverage) const689 int32_t PowerSupplyProvider::ParseCurrentAverage(int32_t* curAverage) const
690 {
691     char buf[MAX_BUFF_SIZE] = {0};
692 
693     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.curAveragePath.c_str(), buf, sizeof(buf));
694     if (ret != HDF_SUCCESS) {
695         return ret;
696     }
697 
698     int32_t value = ParseInt(buf);
699     *curAverage = value;
700 
701     return HDF_SUCCESS;
702 }
703 
ParseCurrentNow(int32_t * curNow) const704 int32_t PowerSupplyProvider::ParseCurrentNow(int32_t* curNow) const
705 {
706     char buf[MAX_BUFF_SIZE] = {0};
707 
708     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.curNowPath.c_str(), buf, sizeof(buf));
709     if (ret != HDF_SUCCESS) {
710         return ret;
711     }
712 
713     int32_t value = ParseInt(buf);
714     *curNow = value;
715 
716     return HDF_SUCCESS;
717 }
718 
ParseRemainEnergy(int32_t * remainEnergy) const719 int32_t PowerSupplyProvider::ParseRemainEnergy(int32_t* remainEnergy) const
720 {
721     char buf[MAX_BUFF_SIZE] = {0};
722 
723     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.remainEnergyPath.c_str(), buf, sizeof(buf));
724     if (ret != HDF_SUCCESS) {
725         return ret;
726     }
727 
728     int32_t value = ParseInt(buf);
729     *remainEnergy = value;
730 
731     return HDF_SUCCESS;
732 }
733 
ParseVoltage(int32_t * voltage) const734 int32_t PowerSupplyProvider::ParseVoltage(int32_t* voltage) const
735 {
736     char buf[MAX_BUFF_SIZE] = {0};
737     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.voltagePath.c_str(), buf, sizeof(buf));
738     if (ret != HDF_SUCCESS) {
739         return ret;
740     }
741 
742     int32_t value = ParseInt(buf);
743     *voltage = value;
744 
745     return HDF_SUCCESS;
746 }
747 
ParseTemperature(int32_t * temperature) const748 int32_t PowerSupplyProvider::ParseTemperature(int32_t* temperature) const
749 {
750     char buf[MAX_BUFF_SIZE] = {0};
751     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.temperaturePath.c_str(), buf, sizeof(buf));
752     if (ret != HDF_SUCCESS) {
753         return ret;
754     }
755 
756     int32_t value = ParseInt(buf);
757     *temperature = value;
758 
759     return HDF_SUCCESS;
760 }
761 
ParseHealthState(int32_t * healthState) const762 int32_t PowerSupplyProvider::ParseHealthState(int32_t* healthState) const
763 {
764     char buf[MAX_BUFF_SIZE] = {0};
765     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.healthStatePath.c_str(), buf, sizeof(buf));
766     if (ret != HDF_SUCCESS) {
767         return ret;
768     }
769 
770     Trim(buf);
771     *healthState = HealthStateEnumConverter(buf);
772     return HDF_SUCCESS;
773 }
774 
ParsePluggedType(int32_t * pluggedType) const775 int32_t PowerSupplyProvider::ParsePluggedType(int32_t* pluggedType) const
776 {
777     char buf[MAX_BUFF_SIZE] = {0};
778     GetPluggedTypeName(buf, sizeof(buf));
779     int32_t type = PluggedTypeEnumConverter(buf);
780     if (type == PLUGGED_TYPE_BUTT) {
781         HDF_LOGW("%{public}s: not support the online type %{public}s", __func__, buf);
782         return HDF_ERR_NOT_SUPPORT;
783     }
784 
785     *pluggedType = type;
786     return HDF_SUCCESS;
787 }
788 
ParseChargeState(int32_t * chargeState) const789 int32_t PowerSupplyProvider::ParseChargeState(int32_t* chargeState) const
790 {
791     char buf[MAX_BUFF_SIZE] = {0};
792     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.chargeStatePath.c_str(), buf, sizeof(buf));
793     if (ret != HDF_SUCCESS) {
794         return ret;
795     }
796 
797     Trim(buf);
798     *chargeState = ChargeStateEnumConverter(buf);
799     return HDF_SUCCESS;
800 }
801 
ParsePresent(int8_t * present) const802 int32_t PowerSupplyProvider::ParsePresent(int8_t* present) const
803 {
804     char buf[MAX_BUFF_SIZE] = {0};
805     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.presentPath.c_str(), buf, sizeof(buf));
806     if (ret != HDF_SUCCESS) {
807         return ret;
808     }
809 
810     int8_t value = (int8_t)ParseInt(buf);
811     *present = value;
812     return HDF_SUCCESS;
813 }
814 
ParseChargeCounter(int32_t * chargeCounter) const815 int32_t PowerSupplyProvider::ParseChargeCounter(int32_t* chargeCounter) const
816 {
817     char buf[MAX_BUFF_SIZE] = {0};
818     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.chargeCounterPath.c_str(), buf, sizeof(buf));
819     if (ret != HDF_SUCCESS) {
820         return ret;
821     }
822 
823     int32_t value = ParseInt(buf);
824     *chargeCounter = value;
825 
826     return HDF_SUCCESS;
827 }
828 
ParseTechnology(std::string & technology) const829 int32_t PowerSupplyProvider::ParseTechnology(std::string& technology) const
830 {
831     char buf[MAX_BUFF_SIZE] = {0};
832     int32_t ret = ReadBatterySysfsToBuff(batterySysfsInfo_.technologyPath.c_str(), buf, sizeof(buf));
833     if (ret != HDF_SUCCESS) {
834         return ret;
835     }
836 
837     technology.assign(buf, strlen(buf));
838     return HDF_SUCCESS;
839 }
840 
GetBatteryInfo() const841 BatterydInfo PowerSupplyProvider::GetBatteryInfo() const
842 {
843     return g_batteryInfo;
844 }
845 
InitDefaultSysfs(void)846 void PowerSupplyProvider::InitDefaultSysfs(void)
847 {
848     std::string mockBatteryPath = "/data/local/tmp/battery";
849     std::string mockChargerPath = "/data/local/tmp/ohos_charger";
850     std::string mockTechPath = "/data/local/tmp/ohos-fgu";
851     if (access(mockBatteryPath.c_str(), 0) == -1) {
852         mkdir("/data/local/tmp/battery", S_IRWXU);
853         sleep(MKDIR_WAIT_TIME);
854     }
855 
856     if (access(mockChargerPath.c_str(), 0) == -1) {
857         mkdir("/data/local/tmp/ohos_charger", S_IRWXU);
858         sleep(MKDIR_WAIT_TIME);
859     }
860 
861     if (access(mockTechPath.c_str(), 0) == -1) {
862         mkdir("/data/local/tmp/ohos-fgu", S_IRWXU);
863         sleep(MKDIR_WAIT_TIME);
864     }
865 
866     HDF_LOGI("%{public}s: create mock path for Hi3516DV300", __func__);
867     CreateFile("/data/local/tmp/ohos-fgu/capacity", "1000");
868     CreateFile("/data/local/tmp/ohos-fgu/current_avg", "1000");
869     CreateFile("/data/local/tmp/ohos-fgu/current_now", "1000");
870     CreateFile("/data/local/tmp/ohos-fgu/health", "Over voltage");
871     CreateFile("/data/local/tmp/ohos-fgu/present", "0");
872     CreateFile("/data/local/tmp/ohos-fgu/status", "Not charging");
873     CreateFile("/data/local/tmp/ohos-fgu/type", "Unknown");
874     CreateFile("/data/local/tmp/ohos-fgu/temp", "345");
875     CreateFile("/data/local/tmp/ohos-fgu/technology", "Li-ion");
876     CreateFile("/data/local/tmp/ohos_charger/type", "USB");
877     CreateFile("/data/local/tmp/ohos_charger/constant_charge_current", "0");
878     CreateFile("/data/local/tmp/ohos_charger/health", "Good");
879     CreateFile("/data/local/tmp/ohos_charger/online", "1");
880     CreateFile("/data/local/tmp/ohos_charger/status", "Charging");
881     CreateFile("/data/local/tmp/ohos_charger/type", "USB");
882     CreateFile("/data/local/tmp/battery/capacity", "11");
883     CreateFile("/data/local/tmp/battery/charge_control_limit", "0");
884     CreateFile("/data/local/tmp/battery/charge_counter", "4000000");
885     CreateFile("/data/local/tmp/battery/charge_full", "4000000");
886     CreateFile("/data/local/tmp/battery/charge_now", "4000000");
887     CreateFile("/data/local/tmp/battery/constant_charge_current", "0");
888     CreateFile("/data/local/tmp/battery/current_avg", "1000");
889     CreateFile("/data/local/tmp/battery/current_now", "1000");
890     CreateFile("/data/local/tmp/battery/health", "Good");
891     CreateFile("/data/local/tmp/battery/input_current_limit", "0");
892     CreateFile("/data/local/tmp/battery/online", "1");
893     CreateFile("/data/local/tmp/battery/present", "0");
894     CreateFile("/data/local/tmp/battery/status", "Full");
895     CreateFile("/data/local/tmp/battery/temp", "222");
896     CreateFile("/data/local/tmp/battery/voltage_avg", "4123456");
897     CreateFile("/data/local/tmp/battery/voltage_now", "4123456");
898     CreateFile("/data/local/tmp/battery/type", "Battery");
899     path_ = "/data/local/tmp";
900 }
901 }  // namespace V1_0
902 }  // namespace Battery
903 }  // namespace HDI
904 }  // namespace OHOS
905