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