• 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 "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