BatteryMonitor.cpp revision e9320b7c927a5344122e921cbb76531204eb2dac
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "healthd" 18 19#include <healthd/healthd.h> 20#include <healthd/BatteryMonitor.h> 21 22#include <dirent.h> 23#include <errno.h> 24#include <fcntl.h> 25#include <stdio.h> 26#include <stdlib.h> 27#include <sys/types.h> 28#include <unistd.h> 29#include <memory> 30 31#include <batteryservice/BatteryService.h> 32#include <cutils/klog.h> 33#include <cutils/properties.h> 34#include <utils/Errors.h> 35#include <utils/String8.h> 36#include <utils/Vector.h> 37 38#define POWER_SUPPLY_SUBSYSTEM "power_supply" 39#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM 40#define FAKE_BATTERY_CAPACITY 42 41#define FAKE_BATTERY_TEMPERATURE 424 42#define ALWAYS_PLUGGED_CAPACITY 100 43 44namespace android { 45 46struct sysfsStringEnumMap { 47 const char* s; 48 int val; 49}; 50 51static int mapSysfsString(const char* str, 52 struct sysfsStringEnumMap map[]) { 53 for (int i = 0; map[i].s; i++) 54 if (!strcmp(str, map[i].s)) 55 return map[i].val; 56 57 return -1; 58} 59 60static void initBatteryProperties(BatteryProperties* props) { 61 props->chargerAcOnline = false; 62 props->chargerUsbOnline = false; 63 props->chargerWirelessOnline = false; 64 props->maxChargingCurrent = 0; 65 props->batteryStatus = BATTERY_STATUS_UNKNOWN; 66 props->batteryHealth = BATTERY_HEALTH_UNKNOWN; 67 props->batteryPresent = false; 68 props->batteryLevel = 0; 69 props->batteryVoltage = 0; 70 props->batteryTemperature = 0; 71 props->batteryCurrent = 0; 72 props->batteryCycleCount = 0; 73 props->batteryFullCharge = 0; 74 props->batteryTechnology.clear(); 75} 76 77BatteryMonitor::BatteryMonitor() : mHealthdConfig(nullptr), mBatteryDevicePresent(false), 78 mAlwaysPluggedDevice(false), mBatteryFixedCapacity(0), mBatteryFixedTemperature(0) { 79 initBatteryProperties(&props); 80} 81 82int BatteryMonitor::getBatteryStatus(const char* status) { 83 int ret; 84 struct sysfsStringEnumMap batteryStatusMap[] = { 85 { "Unknown", BATTERY_STATUS_UNKNOWN }, 86 { "Charging", BATTERY_STATUS_CHARGING }, 87 { "Discharging", BATTERY_STATUS_DISCHARGING }, 88 { "Not charging", BATTERY_STATUS_NOT_CHARGING }, 89 { "Full", BATTERY_STATUS_FULL }, 90 { NULL, 0 }, 91 }; 92 93 ret = mapSysfsString(status, batteryStatusMap); 94 if (ret < 0) { 95 KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status); 96 ret = BATTERY_STATUS_UNKNOWN; 97 } 98 99 return ret; 100} 101 102int BatteryMonitor::getBatteryHealth(const char* status) { 103 int ret; 104 struct sysfsStringEnumMap batteryHealthMap[] = { 105 { "Unknown", BATTERY_HEALTH_UNKNOWN }, 106 { "Good", BATTERY_HEALTH_GOOD }, 107 { "Overheat", BATTERY_HEALTH_OVERHEAT }, 108 { "Dead", BATTERY_HEALTH_DEAD }, 109 { "Over voltage", BATTERY_HEALTH_OVER_VOLTAGE }, 110 { "Unspecified failure", BATTERY_HEALTH_UNSPECIFIED_FAILURE }, 111 { "Cold", BATTERY_HEALTH_COLD }, 112 { NULL, 0 }, 113 }; 114 115 ret = mapSysfsString(status, batteryHealthMap); 116 if (ret < 0) { 117 KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status); 118 ret = BATTERY_HEALTH_UNKNOWN; 119 } 120 121 return ret; 122} 123 124int BatteryMonitor::readFromFile(const String8& path, char* buf, size_t size) { 125 char *cp = NULL; 126 127 if (path.isEmpty()) 128 return -1; 129 int fd = open(path.string(), O_RDONLY, 0); 130 if (fd == -1) { 131 KLOG_ERROR(LOG_TAG, "Could not open '%s'\n", path.string()); 132 return -1; 133 } 134 135 ssize_t count = TEMP_FAILURE_RETRY(read(fd, buf, size)); 136 if (count > 0) 137 cp = (char *)memrchr(buf, '\n', count); 138 139 if (cp) 140 *cp = '\0'; 141 else 142 buf[0] = '\0'; 143 144 close(fd); 145 return count; 146} 147 148BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) { 149 const int SIZE = 128; 150 char buf[SIZE]; 151 int length = readFromFile(path, buf, SIZE); 152 BatteryMonitor::PowerSupplyType ret; 153 struct sysfsStringEnumMap supplyTypeMap[] = { 154 { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN }, 155 { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY }, 156 { "UPS", ANDROID_POWER_SUPPLY_TYPE_AC }, 157 { "Mains", ANDROID_POWER_SUPPLY_TYPE_AC }, 158 { "USB", ANDROID_POWER_SUPPLY_TYPE_USB }, 159 { "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC }, 160 { "USB_HVDCP", ANDROID_POWER_SUPPLY_TYPE_AC }, 161 { "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC }, 162 { "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC }, 163 { "USB_C", ANDROID_POWER_SUPPLY_TYPE_AC }, 164 { "USB_PD", ANDROID_POWER_SUPPLY_TYPE_AC }, 165 { "USB_PD_DRP", ANDROID_POWER_SUPPLY_TYPE_USB }, 166 { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS }, 167 { NULL, 0 }, 168 }; 169 170 if (length <= 0) 171 return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN; 172 173 ret = (BatteryMonitor::PowerSupplyType)mapSysfsString(buf, supplyTypeMap); 174 if (ret < 0) { 175 KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf); 176 ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN; 177 } 178 179 return ret; 180} 181 182bool BatteryMonitor::getBooleanField(const String8& path) { 183 const int SIZE = 16; 184 char buf[SIZE]; 185 186 bool value = false; 187 if (readFromFile(path, buf, SIZE) > 0) { 188 if (buf[0] != '0') { 189 value = true; 190 } 191 } 192 193 return value; 194} 195 196int BatteryMonitor::getIntField(const String8& path) { 197 const int SIZE = 128; 198 char buf[SIZE]; 199 200 int value = 0; 201 if (readFromFile(path, buf, SIZE) > 0) { 202 value = strtol(buf, NULL, 0); 203 } 204 return value; 205} 206 207bool BatteryMonitor::update(void) { 208 bool logthis; 209 210 initBatteryProperties(&props); 211 212 if (!mHealthdConfig->batteryPresentPath.isEmpty()) 213 props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath); 214 else 215 props.batteryPresent = mBatteryDevicePresent; 216 217 props.batteryLevel = mBatteryFixedCapacity ? 218 mBatteryFixedCapacity : 219 getIntField(mHealthdConfig->batteryCapacityPath); 220 props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000; 221 222 if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) 223 props.batteryCurrent = getIntField(mHealthdConfig->batteryCurrentNowPath) / 1000; 224 225 if (!mHealthdConfig->batteryFullChargePath.isEmpty()) 226 props.batteryFullCharge = getIntField(mHealthdConfig->batteryFullChargePath); 227 228 if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) 229 props.batteryCycleCount = getIntField(mHealthdConfig->batteryCycleCountPath); 230 231 props.batteryTemperature = mBatteryFixedTemperature ? 232 mBatteryFixedTemperature : 233 getIntField(mHealthdConfig->batteryTemperaturePath); 234 235 // For devices which do not have battery and are always plugged 236 // into power souce. 237 if (mAlwaysPluggedDevice) { 238 props.chargerAcOnline = true; 239 props.batteryPresent = true; 240 props.batteryStatus = BATTERY_STATUS_CHARGING; 241 props.batteryHealth = BATTERY_HEALTH_GOOD; 242 } 243 244 const int SIZE = 128; 245 char buf[SIZE]; 246 String8 btech; 247 248 if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0) 249 props.batteryStatus = getBatteryStatus(buf); 250 251 if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0) 252 props.batteryHealth = getBatteryHealth(buf); 253 254 if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0) 255 props.batteryTechnology = String8(buf); 256 257 unsigned int i; 258 259 for (i = 0; i < mChargerNames.size(); i++) { 260 String8 path; 261 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, 262 mChargerNames[i].string()); 263 264 if (readFromFile(path, buf, SIZE) > 0) { 265 if (buf[0] != '0') { 266 path.clear(); 267 path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, 268 mChargerNames[i].string()); 269 switch(readPowerSupplyType(path)) { 270 case ANDROID_POWER_SUPPLY_TYPE_AC: 271 props.chargerAcOnline = true; 272 break; 273 case ANDROID_POWER_SUPPLY_TYPE_USB: 274 props.chargerUsbOnline = true; 275 break; 276 case ANDROID_POWER_SUPPLY_TYPE_WIRELESS: 277 props.chargerWirelessOnline = true; 278 break; 279 default: 280 KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n", 281 mChargerNames[i].string()); 282 } 283 path.clear(); 284 path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH, 285 mChargerNames[i].string()); 286 if (access(path.string(), R_OK) == 0) { 287 int maxChargingCurrent = getIntField(path); 288 if (props.maxChargingCurrent < maxChargingCurrent) { 289 props.maxChargingCurrent = maxChargingCurrent; 290 } 291 } 292 } 293 } 294 } 295 296 logthis = !healthd_board_battery_update(&props); 297 298 if (logthis) { 299 char dmesgline[256]; 300 size_t len; 301 if (props.batteryPresent) { 302 snprintf(dmesgline, sizeof(dmesgline), 303 "battery l=%d v=%d t=%s%d.%d h=%d st=%d", 304 props.batteryLevel, props.batteryVoltage, 305 props.batteryTemperature < 0 ? "-" : "", 306 abs(props.batteryTemperature / 10), 307 abs(props.batteryTemperature % 10), props.batteryHealth, 308 props.batteryStatus); 309 310 len = strlen(dmesgline); 311 if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) { 312 len += snprintf(dmesgline + len, sizeof(dmesgline) - len, 313 " c=%d", props.batteryCurrent); 314 } 315 316 if (!mHealthdConfig->batteryFullChargePath.isEmpty()) { 317 len += snprintf(dmesgline + len, sizeof(dmesgline) - len, 318 " fc=%d", props.batteryFullCharge); 319 } 320 321 if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) { 322 len += snprintf(dmesgline + len, sizeof(dmesgline) - len, 323 " cc=%d", props.batteryCycleCount); 324 } 325 } else { 326 len = snprintf(dmesgline, sizeof(dmesgline), 327 "battery none"); 328 } 329 330 snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s", 331 props.chargerAcOnline ? "a" : "", 332 props.chargerUsbOnline ? "u" : "", 333 props.chargerWirelessOnline ? "w" : ""); 334 335 KLOG_WARNING(LOG_TAG, "%s\n", dmesgline); 336 } 337 338 healthd_mode_ops->battery_update(&props); 339 return props.chargerAcOnline | props.chargerUsbOnline | 340 props.chargerWirelessOnline; 341} 342 343int BatteryMonitor::getChargeStatus() { 344 int result = BATTERY_STATUS_UNKNOWN; 345 if (!mHealthdConfig->batteryStatusPath.isEmpty()) { 346 char buf[128]; 347 if (readFromFile(mHealthdConfig->batteryStatusPath, buf, sizeof(buf)) > 0) { 348 result = getBatteryStatus(buf); 349 } 350 } 351 return result; 352} 353 354status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) { 355 status_t ret = BAD_VALUE; 356 357 val->valueInt64 = LONG_MIN; 358 359 switch(id) { 360 case BATTERY_PROP_CHARGE_COUNTER: 361 if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) { 362 val->valueInt64 = 363 getIntField(mHealthdConfig->batteryChargeCounterPath); 364 ret = NO_ERROR; 365 } else { 366 ret = NAME_NOT_FOUND; 367 } 368 break; 369 370 case BATTERY_PROP_CURRENT_NOW: 371 if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) { 372 val->valueInt64 = 373 getIntField(mHealthdConfig->batteryCurrentNowPath); 374 ret = NO_ERROR; 375 } else { 376 ret = NAME_NOT_FOUND; 377 } 378 break; 379 380 case BATTERY_PROP_CURRENT_AVG: 381 if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) { 382 val->valueInt64 = 383 getIntField(mHealthdConfig->batteryCurrentAvgPath); 384 ret = NO_ERROR; 385 } else { 386 ret = NAME_NOT_FOUND; 387 } 388 break; 389 390 case BATTERY_PROP_CAPACITY: 391 if (!mHealthdConfig->batteryCapacityPath.isEmpty()) { 392 val->valueInt64 = 393 getIntField(mHealthdConfig->batteryCapacityPath); 394 ret = NO_ERROR; 395 } else { 396 ret = NAME_NOT_FOUND; 397 } 398 break; 399 400 case BATTERY_PROP_ENERGY_COUNTER: 401 if (mHealthdConfig->energyCounter) { 402 ret = mHealthdConfig->energyCounter(&val->valueInt64); 403 } else { 404 ret = NAME_NOT_FOUND; 405 } 406 break; 407 408 default: 409 break; 410 } 411 412 return ret; 413} 414 415void BatteryMonitor::dumpState(int fd) { 416 int v; 417 char vs[128]; 418 419 snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d current_max: %d\n", 420 props.chargerAcOnline, props.chargerUsbOnline, 421 props.chargerWirelessOnline, props.maxChargingCurrent); 422 write(fd, vs, strlen(vs)); 423 snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n", 424 props.batteryStatus, props.batteryHealth, props.batteryPresent); 425 write(fd, vs, strlen(vs)); 426 snprintf(vs, sizeof(vs), "level: %d voltage: %d temp: %d\n", 427 props.batteryLevel, props.batteryVoltage, 428 props.batteryTemperature); 429 write(fd, vs, strlen(vs)); 430 431 if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) { 432 v = getIntField(mHealthdConfig->batteryCurrentNowPath); 433 snprintf(vs, sizeof(vs), "current now: %d\n", v); 434 write(fd, vs, strlen(vs)); 435 } 436 437 if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) { 438 v = getIntField(mHealthdConfig->batteryCurrentAvgPath); 439 snprintf(vs, sizeof(vs), "current avg: %d\n", v); 440 write(fd, vs, strlen(vs)); 441 } 442 443 if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) { 444 v = getIntField(mHealthdConfig->batteryChargeCounterPath); 445 snprintf(vs, sizeof(vs), "charge counter: %d\n", v); 446 write(fd, vs, strlen(vs)); 447 } 448 449 if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) { 450 snprintf(vs, sizeof(vs), "current now: %d\n", props.batteryCurrent); 451 write(fd, vs, strlen(vs)); 452 } 453 454 if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) { 455 snprintf(vs, sizeof(vs), "cycle count: %d\n", props.batteryCycleCount); 456 write(fd, vs, strlen(vs)); 457 } 458 459 if (!mHealthdConfig->batteryFullChargePath.isEmpty()) { 460 snprintf(vs, sizeof(vs), "Full charge: %d\n", props.batteryFullCharge); 461 write(fd, vs, strlen(vs)); 462 } 463} 464 465void BatteryMonitor::init(struct healthd_config *hc) { 466 String8 path; 467 char pval[PROPERTY_VALUE_MAX]; 468 469 mHealthdConfig = hc; 470 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir); 471 if (dir == NULL) { 472 KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH); 473 } else { 474 struct dirent* entry; 475 476 while ((entry = readdir(dir.get()))) { 477 const char* name = entry->d_name; 478 479 if (!strcmp(name, ".") || !strcmp(name, "..")) 480 continue; 481 482 // Look for "type" file in each subdirectory 483 path.clear(); 484 path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name); 485 switch(readPowerSupplyType(path)) { 486 case ANDROID_POWER_SUPPLY_TYPE_AC: 487 case ANDROID_POWER_SUPPLY_TYPE_USB: 488 case ANDROID_POWER_SUPPLY_TYPE_WIRELESS: 489 path.clear(); 490 path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name); 491 if (access(path.string(), R_OK) == 0) 492 mChargerNames.add(String8(name)); 493 break; 494 495 case ANDROID_POWER_SUPPLY_TYPE_BATTERY: 496 mBatteryDevicePresent = true; 497 498 if (mHealthdConfig->batteryStatusPath.isEmpty()) { 499 path.clear(); 500 path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH, 501 name); 502 if (access(path, R_OK) == 0) 503 mHealthdConfig->batteryStatusPath = path; 504 } 505 506 if (mHealthdConfig->batteryHealthPath.isEmpty()) { 507 path.clear(); 508 path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH, 509 name); 510 if (access(path, R_OK) == 0) 511 mHealthdConfig->batteryHealthPath = path; 512 } 513 514 if (mHealthdConfig->batteryPresentPath.isEmpty()) { 515 path.clear(); 516 path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH, 517 name); 518 if (access(path, R_OK) == 0) 519 mHealthdConfig->batteryPresentPath = path; 520 } 521 522 if (mHealthdConfig->batteryCapacityPath.isEmpty()) { 523 path.clear(); 524 path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH, 525 name); 526 if (access(path, R_OK) == 0) 527 mHealthdConfig->batteryCapacityPath = path; 528 } 529 530 if (mHealthdConfig->batteryVoltagePath.isEmpty()) { 531 path.clear(); 532 path.appendFormat("%s/%s/voltage_now", 533 POWER_SUPPLY_SYSFS_PATH, name); 534 if (access(path, R_OK) == 0) { 535 mHealthdConfig->batteryVoltagePath = path; 536 } else { 537 path.clear(); 538 path.appendFormat("%s/%s/batt_vol", 539 POWER_SUPPLY_SYSFS_PATH, name); 540 if (access(path, R_OK) == 0) 541 mHealthdConfig->batteryVoltagePath = path; 542 } 543 } 544 545 if (mHealthdConfig->batteryFullChargePath.isEmpty()) { 546 path.clear(); 547 path.appendFormat("%s/%s/charge_full", 548 POWER_SUPPLY_SYSFS_PATH, name); 549 if (access(path, R_OK) == 0) 550 mHealthdConfig->batteryFullChargePath = path; 551 } 552 553 if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) { 554 path.clear(); 555 path.appendFormat("%s/%s/current_now", 556 POWER_SUPPLY_SYSFS_PATH, name); 557 if (access(path, R_OK) == 0) 558 mHealthdConfig->batteryCurrentNowPath = path; 559 } 560 561 if (mHealthdConfig->batteryCycleCountPath.isEmpty()) { 562 path.clear(); 563 path.appendFormat("%s/%s/cycle_count", 564 POWER_SUPPLY_SYSFS_PATH, name); 565 if (access(path, R_OK) == 0) 566 mHealthdConfig->batteryCycleCountPath = path; 567 } 568 569 if (mHealthdConfig->batteryCurrentAvgPath.isEmpty()) { 570 path.clear(); 571 path.appendFormat("%s/%s/current_avg", 572 POWER_SUPPLY_SYSFS_PATH, name); 573 if (access(path, R_OK) == 0) 574 mHealthdConfig->batteryCurrentAvgPath = path; 575 } 576 577 if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) { 578 path.clear(); 579 path.appendFormat("%s/%s/charge_counter", 580 POWER_SUPPLY_SYSFS_PATH, name); 581 if (access(path, R_OK) == 0) 582 mHealthdConfig->batteryChargeCounterPath = path; 583 } 584 585 if (mHealthdConfig->batteryTemperaturePath.isEmpty()) { 586 path.clear(); 587 path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH, 588 name); 589 if (access(path, R_OK) == 0) { 590 mHealthdConfig->batteryTemperaturePath = path; 591 } else { 592 path.clear(); 593 path.appendFormat("%s/%s/batt_temp", 594 POWER_SUPPLY_SYSFS_PATH, name); 595 if (access(path, R_OK) == 0) 596 mHealthdConfig->batteryTemperaturePath = path; 597 } 598 } 599 600 if (mHealthdConfig->batteryTechnologyPath.isEmpty()) { 601 path.clear(); 602 path.appendFormat("%s/%s/technology", 603 POWER_SUPPLY_SYSFS_PATH, name); 604 if (access(path, R_OK) == 0) 605 mHealthdConfig->batteryTechnologyPath = path; 606 } 607 608 break; 609 610 case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN: 611 break; 612 } 613 } 614 } 615 616 // This indicates that there is no charger driver registered. 617 // Typically the case for devices which do not have a battery and 618 // and are always plugged into AC mains. 619 if (!mChargerNames.size()) { 620 KLOG_ERROR(LOG_TAG, "No charger supplies found\n"); 621 mBatteryFixedCapacity = ALWAYS_PLUGGED_CAPACITY; 622 mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE; 623 mAlwaysPluggedDevice = true; 624 } 625 if (!mBatteryDevicePresent) { 626 KLOG_WARNING(LOG_TAG, "No battery devices found\n"); 627 hc->periodic_chores_interval_fast = -1; 628 hc->periodic_chores_interval_slow = -1; 629 } else { 630 if (mHealthdConfig->batteryStatusPath.isEmpty()) 631 KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n"); 632 if (mHealthdConfig->batteryHealthPath.isEmpty()) 633 KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n"); 634 if (mHealthdConfig->batteryPresentPath.isEmpty()) 635 KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n"); 636 if (mHealthdConfig->batteryCapacityPath.isEmpty()) 637 KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n"); 638 if (mHealthdConfig->batteryVoltagePath.isEmpty()) 639 KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n"); 640 if (mHealthdConfig->batteryTemperaturePath.isEmpty()) 641 KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n"); 642 if (mHealthdConfig->batteryTechnologyPath.isEmpty()) 643 KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n"); 644 if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) 645 KLOG_WARNING(LOG_TAG, "BatteryCurrentNowPath not found\n"); 646 if (mHealthdConfig->batteryFullChargePath.isEmpty()) 647 KLOG_WARNING(LOG_TAG, "BatteryFullChargePath not found\n"); 648 if (mHealthdConfig->batteryCycleCountPath.isEmpty()) 649 KLOG_WARNING(LOG_TAG, "BatteryCycleCountPath not found\n"); 650 } 651 652 if (property_get("ro.boot.fake_battery", pval, NULL) > 0 653 && strtol(pval, NULL, 10) != 0) { 654 mBatteryFixedCapacity = FAKE_BATTERY_CAPACITY; 655 mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE; 656 } 657} 658 659}; // namespace android 660