summaryrefslogtreecommitdiffstats
path: root/healthd
diff options
context:
space:
mode:
Diffstat (limited to 'healthd')
-rw-r--r--healthd/Android.mk21
-rw-r--r--healthd/BatteryMonitor.cpp371
-rw-r--r--healthd/BatteryMonitor.h7
-rw-r--r--healthd/BatteryPropertiesRegistrar.cpp5
-rw-r--r--healthd/BatteryPropertiesRegistrar.h2
-rw-r--r--healthd/healthd.cpp27
-rw-r--r--healthd/healthd.h50
-rw-r--r--healthd/healthd_board_default.cpp22
-rw-r--r--healthd/healthd_mode_charger.cpp143
9 files changed, 596 insertions, 52 deletions
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 07e1d73..e5fffc0 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -25,6 +25,18 @@ LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
LOCAL_CFLAGS := -D__STDC_LIMIT_MACROS -Werror
+HEALTHD_CHARGER_DEFINES := RED_LED_PATH \
+ GREEN_LED_PATH \
+ BLUE_LED_PATH \
+ BACKLIGHT_PATH \
+ CHARGING_ENABLED_PATH
+
+$(foreach healthd_charger_define,$(HEALTHD_CHARGER_DEFINES), \
+ $(if $($(healthd_charger_define)), \
+ $(eval LOCAL_CFLAGS += -D$(healthd_charger_define)=\"$($(healthd_charger_define))\") \
+ ) \
+)
+
ifeq ($(strip $(BOARD_CHARGER_DISABLE_INIT_BLANK)),true)
LOCAL_CFLAGS += -DCHARGER_DISABLE_INIT_BLANK
endif
@@ -45,7 +57,7 @@ LOCAL_HAL_STATIC_LIBRARIES := libhealthd
# Symlink /charger to /sbin/healthd
LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT) \
- && ln -sf /sbin/healthd $(TARGET_ROOT_OUT)/charger
+ && rm -f $(TARGET_ROOT_OUT)/charger && ln -sf /sbin/healthd $(TARGET_ROOT_OUT)/charger
include $(BUILD_EXECUTABLE)
@@ -63,8 +75,13 @@ include $$(BUILD_PREBUILT)
endef
_img_modules :=
+ifeq ($(strip $(BOARD_HEALTHD_CUSTOM_CHARGER_RES)),)
+IMAGES_DIR := images
+else
+IMAGES_DIR := ../../../$(BOARD_HEALTHD_CUSTOM_CHARGER_RES)
+endif
_images :=
-$(foreach _img, $(call find-subdir-subdir-files, "images", "*.png"), \
+$(foreach _img, $(call find-subdir-subdir-files, "$(IMAGES_DIR)", "*.png"), \
$(eval $(call _add-charger-image,$(_img))))
include $(CLEAR_VARS)
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 396dfef..67a8ad0 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -137,7 +138,12 @@ BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String
{ "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC },
{ "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC },
{ "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC },
+ { "USB_HVDCP", ANDROID_POWER_SUPPLY_TYPE_AC },
+ { "USB_HVDCP_3", ANDROID_POWER_SUPPLY_TYPE_AC },
{ "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
+ { "Wipower", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
+ { "DockBattery", ANDROID_POWER_SUPPLY_TYPE_DOCK_BATTERY },
+ { "DockAC", ANDROID_POWER_SUPPLY_TYPE_DOCK_AC },
{ NULL, 0 },
};
@@ -182,9 +188,12 @@ bool BatteryMonitor::update(void) {
props.chargerAcOnline = false;
props.chargerUsbOnline = false;
props.chargerWirelessOnline = false;
+ props.chargerDockAcOnline = false;
props.batteryStatus = BATTERY_STATUS_UNKNOWN;
props.batteryHealth = BATTERY_HEALTH_UNKNOWN;
props.maxChargingCurrent = 0;
+ props.dockBatteryStatus = BATTERY_STATUS_UNKNOWN;
+ props.dockBatteryHealth = BATTERY_HEALTH_UNKNOWN;
if (!mHealthdConfig->batteryPresentPath.isEmpty())
props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
@@ -222,53 +231,109 @@ bool BatteryMonitor::update(void) {
if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0)
props.batteryTechnology = String8(buf);
- unsigned int i;
+ props.dockBatterySupported = mHealthdConfig->dockBatterySupported;
+ if (props.dockBatterySupported) {
+ if (!mHealthdConfig->dockBatteryPresentPath.isEmpty())
+ props.dockBatteryPresent = getBooleanField(mHealthdConfig->dockBatteryPresentPath);
+ else
+ props.dockBatteryPresent = mDockBatteryDevicePresent;
- for (i = 0; i < mChargerNames.size(); i++) {
- String8 path;
- path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
- mChargerNames[i].string());
+ props.dockBatteryLevel = mBatteryFixedCapacity ?
+ mBatteryFixedCapacity :
+ getIntField(mHealthdConfig->dockBatteryCapacityPath);
+ props.dockBatteryVoltage = getIntField(mHealthdConfig->dockBatteryVoltagePath) / 1000;
- if (readFromFile(path, buf, SIZE) > 0) {
- if (buf[0] != '0') {
- path.clear();
- path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
- mChargerNames[i].string());
- switch(readPowerSupplyType(path)) {
- case ANDROID_POWER_SUPPLY_TYPE_AC:
- props.chargerAcOnline = true;
- break;
- case ANDROID_POWER_SUPPLY_TYPE_USB:
- props.chargerUsbOnline = true;
- break;
- case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
- props.chargerWirelessOnline = true;
- break;
- default:
- KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
- mChargerNames[i].string());
- }
+ props.dockBatteryTemperature = mBatteryFixedTemperature ?
+ mBatteryFixedTemperature :
+ getIntField(mHealthdConfig->dockBatteryTemperaturePath);
+
+ if (readFromFile(mHealthdConfig->dockBatteryStatusPath, buf, SIZE) > 0)
+ props.dockBatteryStatus = getBatteryStatus(buf);
+
+ if (readFromFile(mHealthdConfig->dockBatteryHealthPath, buf, SIZE) > 0)
+ props.dockBatteryHealth = getBatteryHealth(buf);
+
+ if (readFromFile(mHealthdConfig->dockBatteryTechnologyPath, buf, SIZE) > 0)
+ props.dockBatteryTechnology = String8(buf);
+ }
+
+ // reinitialize the mChargerNames vector everytime there is an update
+ String8 path;
+ DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);
+ if (dir == NULL) {
+ KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
+ } else {
+ struct dirent* entry;
+ // reconstruct the charger strings
+ mChargerNames.clear();
+ while ((entry = readdir(dir))) {
+ const char* name = entry->d_name;
+
+ if (!strcmp(name, ".") || !strcmp(name, ".."))
+ continue;
+
+ // Look for "type" file in each subdirectory
+ path.clear();
+ path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
+ switch(readPowerSupplyType(path)) {
+ case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
+ case ANDROID_POWER_SUPPLY_TYPE_DOCK_BATTERY:
+ break;
+ default:
path.clear();
- path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
- mChargerNames[i].string());
+ path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
if (access(path.string(), R_OK) == 0) {
- int maxChargingCurrent = getIntField(path);
- if (props.maxChargingCurrent < maxChargingCurrent) {
- props.maxChargingCurrent = maxChargingCurrent;
+ mChargerNames.add(String8(name));
+ if (readFromFile(path, buf, SIZE) > 0) {
+ if (buf[0] != '0') {
+ path.clear();
+ path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ switch(readPowerSupplyType(path)) {
+ case ANDROID_POWER_SUPPLY_TYPE_AC:
+ props.chargerAcOnline = true;
+ break;
+ case ANDROID_POWER_SUPPLY_TYPE_USB:
+ props.chargerUsbOnline = true;
+ break;
+ case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
+ props.chargerWirelessOnline = true;
+ break;
+ case ANDROID_POWER_SUPPLY_TYPE_DOCK_AC:
+ if (mHealthdConfig->dockBatterySupported) {
+ props.chargerDockAcOnline = true;
+ }
+ default:
+ KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
+ name);
+ }
+ path.clear();
+ path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ if (access(path.string(), R_OK) == 0) {
+ int maxChargingCurrent = getIntField(path);
+ if (props.maxChargingCurrent < maxChargingCurrent) {
+ props.maxChargingCurrent = maxChargingCurrent;
+ }
+ }
+ }
}
}
- }
- }
- }
+ break;
+ } //switch
+ } //while
+ closedir(dir);
+ }//else
logthis = !healthd_board_battery_update(&props);
if (logthis) {
char dmesgline[256];
+ char dmesglinedock[256];
if (props.batteryPresent) {
snprintf(dmesgline, sizeof(dmesgline),
- "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
+ "battery [l=%d v=%d t=%s%d.%d h=%d st=%d]",
props.batteryLevel, props.batteryVoltage,
props.batteryTemperature < 0 ? "-" : "",
abs(props.batteryTemperature / 10),
@@ -287,6 +352,27 @@ bool BatteryMonitor::update(void) {
"battery none");
}
+ if (props.dockBatteryPresent) {
+ snprintf(dmesglinedock, sizeof(dmesglinedock),
+ "dock-battery [l=%d v=%d t=%s%d.%d h=%d st=%d]",
+ props.dockBatteryLevel, props.dockBatteryVoltage,
+ props.dockBatteryTemperature < 0 ? "-" : "",
+ abs(props.dockBatteryTemperature / 10),
+ abs(props.dockBatteryTemperature % 10), props.dockBatteryHealth,
+ props.dockBatteryStatus);
+
+ if (!mHealthdConfig->dockBatteryCurrentNowPath.isEmpty()) {
+ int c = getIntField(mHealthdConfig->dockBatteryCurrentNowPath);
+ char b[20];
+
+ snprintf(b, sizeof(b), " c=%d", c / 1000);
+ strlcat(dmesglinedock, b, sizeof(dmesglinedock));
+ }
+ } else {
+ snprintf(dmesglinedock, sizeof(dmesglinedock),
+ "dock-battery none");
+ }
+
size_t len = strlen(dmesgline);
snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
props.chargerAcOnline ? "a" : "",
@@ -317,7 +403,7 @@ bool BatteryMonitor::update(void) {
healthd_mode_ops->battery_update(&props);
return props.chargerAcOnline | props.chargerUsbOnline |
- props.chargerWirelessOnline;
+ props.chargerWirelessOnline | props.chargerDockAcOnline;
}
status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
@@ -381,13 +467,77 @@ status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
return ret;
}
+status_t BatteryMonitor::getDockProperty(int id, struct BatteryProperty *val) {
+ status_t ret = BAD_VALUE;
+ if (!mHealthdConfig->dockBatterySupported) {
+ return ret;
+ }
+
+ val->valueInt64 = LONG_MIN;
+
+ switch(id) {
+ case BATTERY_PROP_CHARGE_COUNTER:
+ if (!mHealthdConfig->dockBatteryChargeCounterPath.isEmpty()) {
+ val->valueInt64 =
+ getIntField(mHealthdConfig->dockBatteryChargeCounterPath);
+ ret = NO_ERROR;
+ } else {
+ ret = NAME_NOT_FOUND;
+ }
+ break;
+
+ case BATTERY_PROP_CURRENT_NOW:
+ if (!mHealthdConfig->dockBatteryCurrentNowPath.isEmpty()) {
+ val->valueInt64 =
+ getIntField(mHealthdConfig->dockBatteryCurrentNowPath);
+ ret = NO_ERROR;
+ } else {
+ ret = NAME_NOT_FOUND;
+ }
+ break;
+
+ case BATTERY_PROP_CURRENT_AVG:
+ if (!mHealthdConfig->dockBatteryCurrentAvgPath.isEmpty()) {
+ val->valueInt64 =
+ getIntField(mHealthdConfig->dockBatteryCurrentAvgPath);
+ ret = NO_ERROR;
+ } else {
+ ret = NAME_NOT_FOUND;
+ }
+ break;
+
+ case BATTERY_PROP_CAPACITY:
+ if (!mHealthdConfig->dockBatteryCapacityPath.isEmpty()) {
+ val->valueInt64 =
+ getIntField(mHealthdConfig->dockBatteryCapacityPath);
+ ret = NO_ERROR;
+ } else {
+ ret = NAME_NOT_FOUND;
+ }
+ break;
+
+ case BATTERY_PROP_ENERGY_COUNTER:
+ if (mHealthdConfig->dockEnergyCounter) {
+ ret = mHealthdConfig->dockEnergyCounter(&val->valueInt64);
+ } else {
+ ret = NAME_NOT_FOUND;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
void BatteryMonitor::dumpState(int fd) {
int v;
char vs[128];
- snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d current_max: %d\n",
+ snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d dock-ac: %d current_max: %d\n",
props.chargerAcOnline, props.chargerUsbOnline,
- props.chargerWirelessOnline, props.maxChargingCurrent);
+ props.chargerWirelessOnline, props.chargerDockAcOnline, props.maxChargingCurrent);
write(fd, vs, strlen(vs));
snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n",
props.batteryStatus, props.batteryHealth, props.batteryPresent);
@@ -414,6 +564,34 @@ void BatteryMonitor::dumpState(int fd) {
snprintf(vs, sizeof(vs), "charge counter: %d\n", v);
write(fd, vs, strlen(vs));
}
+
+ if (mHealthdConfig->dockBatterySupported) {
+ snprintf(vs, sizeof(vs), "dock-status: %d dock-health: %d dock-present: %d\n",
+ props.dockBatteryStatus, props.dockBatteryHealth, props.dockBatteryPresent);
+ write(fd, vs, strlen(vs));
+ snprintf(vs, sizeof(vs), "dock-level: %d dock-voltage: %d dock-temp: %d\n",
+ props.dockBatteryLevel, props.dockBatteryVoltage,
+ props.dockBatteryTemperature);
+ write(fd, vs, strlen(vs));
+
+ if (!mHealthdConfig->dockBatteryCurrentNowPath.isEmpty()) {
+ v = getIntField(mHealthdConfig->dockBatteryCurrentNowPath);
+ snprintf(vs, sizeof(vs), "dock-current now: %d\n", v);
+ write(fd, vs, strlen(vs));
+ }
+
+ if (!mHealthdConfig->dockBatteryCurrentAvgPath.isEmpty()) {
+ v = getIntField(mHealthdConfig->dockBatteryCurrentAvgPath);
+ snprintf(vs, sizeof(vs), "dock-current avg: %d\n", v);
+ write(fd, vs, strlen(vs));
+ }
+
+ if (!mHealthdConfig->dockBatteryChargeCounterPath.isEmpty()) {
+ v = getIntField(mHealthdConfig->dockBatteryChargeCounterPath);
+ snprintf(vs, sizeof(vs), "dock-charge counter: %d\n", v);
+ write(fd, vs, strlen(vs));
+ }
+ }
}
void BatteryMonitor::init(struct healthd_config *hc) {
@@ -440,6 +618,7 @@ void BatteryMonitor::init(struct healthd_config *hc) {
case ANDROID_POWER_SUPPLY_TYPE_AC:
case ANDROID_POWER_SUPPLY_TYPE_USB:
case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
+ case ANDROID_POWER_SUPPLY_TYPE_DOCK_AC:
path.clear();
path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
if (access(path.string(), R_OK) == 0)
@@ -545,6 +724,107 @@ void BatteryMonitor::init(struct healthd_config *hc) {
break;
+ case ANDROID_POWER_SUPPLY_TYPE_DOCK_BATTERY:
+ if (mHealthdConfig->dockBatterySupported) {
+ mDockBatteryDevicePresent = true;
+
+ if (mHealthdConfig->dockBatteryStatusPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->dockBatteryStatusPath = path;
+ }
+
+ if (mHealthdConfig->dockBatteryHealthPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->dockBatteryHealthPath = path;
+ }
+
+ if (mHealthdConfig->dockBatteryPresentPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->dockBatteryPresentPath = path;
+ }
+
+ if (mHealthdConfig->dockBatteryCapacityPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->dockBatteryCapacityPath = path;
+ }
+
+ if (mHealthdConfig->dockBatteryVoltagePath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/voltage_now",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0) {
+ mHealthdConfig->dockBatteryVoltagePath = path;
+ } else {
+ path.clear();
+ path.appendFormat("%s/%s/batt_vol",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->dockBatteryVoltagePath = path;
+ }
+ }
+
+ if (mHealthdConfig->dockBatteryCurrentNowPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/current_now",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->dockBatteryCurrentNowPath = path;
+ }
+
+ if (mHealthdConfig->dockBatteryCurrentAvgPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/current_avg",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->dockBatteryCurrentAvgPath = path;
+ }
+
+ if (mHealthdConfig->dockBatteryChargeCounterPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/charge_counter",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->dockBatteryChargeCounterPath = path;
+ }
+
+ if (mHealthdConfig->dockBatteryTemperaturePath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
+ name);
+ if (access(path, R_OK) == 0) {
+ mHealthdConfig->dockBatteryTemperaturePath = path;
+ } else {
+ path.clear();
+ path.appendFormat("%s/%s/batt_temp",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->dockBatteryTemperaturePath = path;
+ }
+ }
+
+ if (mHealthdConfig->dockBatteryTechnologyPath.isEmpty()) {
+ path.clear();
+ path.appendFormat("%s/%s/technology",
+ POWER_SUPPLY_SYSFS_PATH, name);
+ if (access(path, R_OK) == 0)
+ mHealthdConfig->dockBatteryTechnologyPath = path;
+ }
+ }
+
+ break;
+
case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
break;
}
@@ -561,7 +841,7 @@ void BatteryMonitor::init(struct healthd_config *hc) {
mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
mAlwaysPluggedDevice = true;
}
- if (!mBatteryDevicePresent) {
+ if (!mBatteryDevicePresent && !mDockBatteryDevicePresent) {
KLOG_WARNING(LOG_TAG, "No battery devices found\n");
hc->periodic_chores_interval_fast = -1;
hc->periodic_chores_interval_slow = -1;
@@ -580,6 +860,23 @@ void BatteryMonitor::init(struct healthd_config *hc) {
KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
if (mHealthdConfig->batteryTechnologyPath.isEmpty())
KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
+
+ if (mHealthdConfig->dockBatterySupported) {
+ if (mHealthdConfig->dockBatteryStatusPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "DockBatteryStatusPath not found\n");
+ if (mHealthdConfig->dockBatteryHealthPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "DockBatteryHealthPath not found\n");
+ if (mHealthdConfig->dockBatteryPresentPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "DockBatteryPresentPath not found\n");
+ if (mHealthdConfig->dockBatteryCapacityPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "DockBatteryCapacityPath not found\n");
+ if (mHealthdConfig->dockBatteryVoltagePath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "DockBatteryVoltagePath not found\n");
+ if (mHealthdConfig->dockBatteryTemperaturePath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "DockBatteryTemperaturePath not found\n");
+ if (mHealthdConfig->dockBatteryTechnologyPath.isEmpty())
+ KLOG_WARNING(LOG_TAG, "DockBatteryTechnologyPath not found\n");
+ }
}
if (property_get("ro.boot.fake_battery", pval, NULL) > 0
diff --git a/healthd/BatteryMonitor.h b/healthd/BatteryMonitor.h
index a61171f..4320348 100644
--- a/healthd/BatteryMonitor.h
+++ b/healthd/BatteryMonitor.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,18 +35,22 @@ class BatteryMonitor {
ANDROID_POWER_SUPPLY_TYPE_AC,
ANDROID_POWER_SUPPLY_TYPE_USB,
ANDROID_POWER_SUPPLY_TYPE_WIRELESS,
- ANDROID_POWER_SUPPLY_TYPE_BATTERY
+ ANDROID_POWER_SUPPLY_TYPE_BATTERY,
+ ANDROID_POWER_SUPPLY_TYPE_DOCK_AC,
+ ANDROID_POWER_SUPPLY_TYPE_DOCK_BATTERY
};
void init(struct healthd_config *hc);
bool update(void);
status_t getProperty(int id, struct BatteryProperty *val);
+ status_t getDockProperty(int id, struct BatteryProperty *val);
void dumpState(int fd);
private:
struct healthd_config *mHealthdConfig;
Vector<String8> mChargerNames;
bool mBatteryDevicePresent;
+ bool mDockBatteryDevicePresent;
bool mAlwaysPluggedDevice;
int mBatteryFixedCapacity;
int mBatteryFixedTemperature;
diff --git a/healthd/BatteryPropertiesRegistrar.cpp b/healthd/BatteryPropertiesRegistrar.cpp
index 09667a1..7a28ead 100644
--- a/healthd/BatteryPropertiesRegistrar.cpp
+++ b/healthd/BatteryPropertiesRegistrar.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -76,6 +77,10 @@ status_t BatteryPropertiesRegistrar::getProperty(int id, struct BatteryProperty
return healthd_get_property(id, val);
}
+status_t BatteryPropertiesRegistrar::getDockProperty(int id, struct BatteryProperty *val) {
+ return healthd_get_dock_property(id, val);
+}
+
status_t BatteryPropertiesRegistrar::dump(int fd, const Vector<String16>& /*args*/) {
IPCThreadState* self = IPCThreadState::self();
const int pid = self->getCallingPid();
diff --git a/healthd/BatteryPropertiesRegistrar.h b/healthd/BatteryPropertiesRegistrar.h
index 8853874..5ca4fc1 100644
--- a/healthd/BatteryPropertiesRegistrar.h
+++ b/healthd/BatteryPropertiesRegistrar.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,6 +41,7 @@ private:
void registerListener(const sp<IBatteryPropertiesListener>& listener);
void unregisterListener(const sp<IBatteryPropertiesListener>& listener);
status_t getProperty(int id, struct BatteryProperty *val);
+ status_t getDockProperty(int id, struct BatteryProperty *val);
status_t dump(int fd, const Vector<String16>& args);
void binderDied(const wp<IBinder>& who);
};
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index b0002cc..1489912 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,8 +37,15 @@
using namespace android;
// Periodic chores intervals in seconds
+#ifdef QCOM_HARDWARE
+#define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 10)
+//For the designs without low battery detection,need to enable
+//the default 60*10s wakeup timer to periodic check.
+#define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW -1
+#else
#define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1)
#define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10)
+#endif
static struct healthd_config healthd_config = {
.periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST,
@@ -55,6 +63,18 @@ static struct healthd_config healthd_config = {
.energyCounter = NULL,
.boot_min_cap = 0,
.screen_on = NULL,
+ .dockBatterySupported = false,
+ .dockBatteryStatusPath = String8(String8::kEmptyString),
+ .dockBatteryHealthPath = String8(String8::kEmptyString),
+ .dockBatteryPresentPath = String8(String8::kEmptyString),
+ .dockBatteryCapacityPath = String8(String8::kEmptyString),
+ .dockBatteryVoltagePath = String8(String8::kEmptyString),
+ .dockBatteryTemperaturePath = String8(String8::kEmptyString),
+ .dockBatteryTechnologyPath = String8(String8::kEmptyString),
+ .dockBatteryCurrentNowPath = String8(String8::kEmptyString),
+ .dockBatteryCurrentAvgPath = String8(String8::kEmptyString),
+ .dockBatteryChargeCounterPath = String8(String8::kEmptyString),
+ .dockEnergyCounter = NULL,
};
static int eventct;
@@ -173,6 +193,10 @@ status_t healthd_get_property(int id, struct BatteryProperty *val) {
return gBatteryMonitor->getProperty(id, val);
}
+status_t healthd_get_dock_property(int id, struct BatteryProperty *val) {
+ return gBatteryMonitor->getDockProperty(id, val);
+}
+
void healthd_battery_update(void) {
// Fast wake interval when on charger (watch for overheat);
// slow wake interval when on battery (watch for drained battery).
@@ -357,6 +381,9 @@ int main(int argc, char **argv) {
exit(2);
}
+ periodic_chores();
+ healthd_mode_ops->heartbeat();
+
healthd_mainloop();
KLOG_ERROR("Main loop terminated, exiting\n");
return 3;
diff --git a/healthd/healthd.h b/healthd/healthd.h
index 84b6d76..0b2a16e 100644
--- a/healthd/healthd.h
+++ b/healthd/healthd.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2015 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,8 +49,25 @@
// batteryTemperaturePath: battery temperature (POWER_SUPPLY_PROP_TEMP)
// batteryTechnologyPath: battery technology (POWER_SUPPLY_PROP_TECHNOLOGY)
// batteryCurrentNowPath: battery current (POWER_SUPPLY_PROP_CURRENT_NOW)
+// batteryCurrentAvgPath: battery average (POWER_SUPPLY_PROP_CURRENT_AVG)
// batteryChargeCounterPath: battery accumulated charge
// (POWER_SUPPLY_PROP_CHARGE_COUNTER)
+//
+// dockBatteryStatusPath: dock charging status (POWER_SUPPLY_PROP_STATUS)
+// dockBatteryHealthPath: dock battery health (POWER_SUPPLY_PROP_HEALTH)
+// dockBatteryPresentPath: dock battery present (POWER_SUPPLY_PROP_PRESENT)
+// dockBatteryCapacityPath: remaining dock capacity (POWER_SUPPLY_PROP_CAPACITY)
+// dockBatteryVoltagePath: dock battery voltage (POWER_SUPPLY_PROP_VOLTAGE_NOW)
+// dockBatteryTemperaturePath: dock battery temperature (POWER_SUPPLY_PROP_TEMP)
+// dockBatteryTechnologyPath: dock battery technology (POWER_SUPPLY_PROP_TECHNOLOGY)
+// dockBatteryCurrentNowPath: dock battery current (POWER_SUPPLY_PROP_CURRENT_NOW)
+// dockBatteryCurrentAvgPath: dock battery average (POWER_SUPPLY_PROP_CURRENT_AVG)
+// dockBatteryChargeCounterPath: dock battery accumulated charge
+// (POWER_SUPPLY_PROP_CHARGE_COUNTER)
+//
+// The dockBatterySupported property indicates whether a dock battery is supported
+// by the device, and whether this module should fetch dock battery values.
+// Defaults is to false.
struct healthd_config {
int periodic_chores_interval_fast;
@@ -69,6 +87,20 @@ struct healthd_config {
int (*energyCounter)(int64_t *);
int boot_min_cap;
bool (*screen_on)(android::BatteryProperties *props);
+
+ bool dockBatterySupported;
+ android::String8 dockBatteryStatusPath;
+ android::String8 dockBatteryHealthPath;
+ android::String8 dockBatteryPresentPath;
+ android::String8 dockBatteryCapacityPath;
+ android::String8 dockBatteryVoltagePath;
+ android::String8 dockBatteryTemperaturePath;
+ android::String8 dockBatteryTechnologyPath;
+ android::String8 dockBatteryCurrentNowPath;
+ android::String8 dockBatteryCurrentAvgPath;
+ android::String8 dockBatteryChargeCounterPath;
+
+ int (*dockEnergyCounter)(int64_t *);
};
// Global helper functions
@@ -77,6 +109,8 @@ int healthd_register_event(int fd, void (*handler)(uint32_t));
void healthd_battery_update();
android::status_t healthd_get_property(int id,
struct android::BatteryProperty *val);
+android::status_t healthd_get_dock_property(int id,
+ struct android::BatteryProperty *val);
void healthd_dump_battery_state(int fd);
struct healthd_mode_ops {
@@ -121,4 +155,20 @@ void healthd_board_init(struct healthd_config *config);
int healthd_board_battery_update(struct android::BatteryProperties *props);
+//This API is called to turn on/off the display backlight incase it can't be
+//handle correcty in the display driver by calling gr_fg_blank();
+void healthd_board_mode_charger_set_backlight(bool en);
+
+//This API is called to update the battery/charging status by using the user
+//noticeable method other then the animation, such as: LEDs
+void healthd_board_mode_charger_battery_update(struct android::BatteryProperties *batt_prop);
+
+//This API is used to handle some board specific charger mode initialization,
+//such as: checking the charging is enabled or not.
+void healthd_board_mode_charger_init(void);
+
+//This API is called in the draw_battery() function to draw more infomation
+//about the battery on the animation, such as the SoC (State of Charge).
+void healthd_board_mode_charger_draw_battery(struct android::BatteryProperties *batt_prop);
+
#endif /* _HEALTHD_H_ */
diff --git a/healthd/healthd_board_default.cpp b/healthd/healthd_board_default.cpp
index ed4ddb4..c511c9c 100644
--- a/healthd/healthd_board_default.cpp
+++ b/healthd/healthd_board_default.cpp
@@ -25,5 +25,25 @@ void healthd_board_init(struct healthd_config*)
int healthd_board_battery_update(struct android::BatteryProperties*)
{
// return 0 to log periodic polled battery status to kernel log
- return 0;
+ return 1;
+}
+
+void healthd_board_mode_charger_draw_battery(struct android::BatteryProperties*)
+{
+
+}
+
+void healthd_board_mode_charger_battery_update(struct android::BatteryProperties*)
+{
+
+}
+
+void healthd_board_mode_charger_set_backlight(bool)
+{
+
+}
+
+void healthd_board_mode_charger_init()
+{
+
}
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 6800ad2..1b6e216 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -65,13 +65,22 @@ char *locale;
#define BATTERY_UNKNOWN_TIME (2 * MSEC_PER_SEC)
#define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC)
-#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC)
+#define UNPLUGGED_SHUTDOWN_TIME (5 * MSEC_PER_SEC)
#define BATTERY_FULL_THRESH 95
#define LAST_KMSG_PATH "/proc/last_kmsg"
#define LAST_KMSG_PSTORE_PATH "/sys/fs/pstore/console-ramoops"
#define LAST_KMSG_MAX_SZ (32 * 1024)
+#ifndef RED_LED_PATH
+#define RED_LED_PATH "/sys/class/leds/red/brightness"
+#endif
+#ifndef GREEN_LED_PATH
+#define GREEN_LED_PATH "/sys/class/leds/green/brightness"
+#endif
+#ifndef BLUE_LED_PATH
+#define BLUE_LED_PATH "/sys/class/leds/blue/brightness"
+#endif
#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0)
#define LOGW(x...) do { KLOG_WARNING("charger", x); } while (0)
@@ -168,6 +177,33 @@ static struct animation battery_animation = {
.capacity = 0,
};
+enum {
+ RED_LED = 0x01 << 0,
+ GREEN_LED = 0x01 << 1,
+ BLUE_LED = 0x01 << 2,
+};
+
+struct led_ctl {
+ int color;
+ const char *path;
+};
+
+struct led_ctl leds[3] =
+ {{RED_LED, RED_LED_PATH},
+ {GREEN_LED, GREEN_LED_PATH},
+ {BLUE_LED, BLUE_LED_PATH}};
+
+struct soc_led_color_mapping {
+ int soc;
+ int color;
+};
+
+struct soc_led_color_mapping soc_leds[3] = {
+ {15, RED_LED},
+ {90, RED_LED | GREEN_LED},
+ {100, GREEN_LED},
+};
+
static struct charger charger_state;
static struct healthd_config *healthd_config;
static struct android::BatteryProperties *batt_prop;
@@ -175,6 +211,53 @@ static int char_width;
static int char_height;
static bool minui_inited;
+static int set_tricolor_led(int on, int color)
+{
+ int fd, i;
+ char buffer[10];
+
+ for (i = 0; i < (int)ARRAY_SIZE(leds); i++) {
+ if ((color & leds[i].color) && (access(leds[i].path, R_OK | W_OK) == 0)) {
+ fd = open(leds[i].path, O_RDWR);
+ if (fd < 0) {
+ LOGE("Could not open led node %d\n", i);
+ continue;
+ }
+ if (on)
+ snprintf(buffer, sizeof(int), "%d\n", 255);
+ else
+ snprintf(buffer, sizeof(int), "%d\n", 0);
+
+ if (write(fd, buffer, strlen(buffer)) < 0)
+ LOGE("Could not write to led node\n");
+ if (fd >= 0)
+ close(fd);
+ }
+ }
+
+ return 0;
+}
+
+static int set_battery_soc_leds(int soc)
+{
+ int i, color;
+ static int old_color = 0;
+
+ for (i = 0; i < (int)ARRAY_SIZE(soc_leds); i++) {
+ if (soc <= soc_leds[i].soc)
+ break;
+ }
+ color = soc_leds[i].color;
+ if (old_color != color) {
+ set_tricolor_led(0, old_color);
+ set_tricolor_led(1, color);
+ old_color = color;
+ LOGV("soc = %d, set led color 0x%x\n", soc, soc_leds[i].color);
+ }
+
+ return 0;
+}
+
/* current time in milliseconds */
static int64_t curr_time_ms(void)
{
@@ -314,6 +397,7 @@ static void draw_battery(struct charger *charger)
batt_anim->cur_frame, frame->min_capacity,
frame->disp_time);
}
+ healthd_board_mode_charger_draw_battery(batt_prop);
}
static void redraw_screen(struct charger *charger)
@@ -367,6 +451,7 @@ static void update_screen_state(struct charger *charger, int64_t now)
gr_font_size(&char_width, &char_height);
#ifndef CHARGER_DISABLE_INIT_BLANK
+ healthd_board_mode_charger_set_backlight(false);
gr_fb_blank(true);
#endif
minui_inited = true;
@@ -376,6 +461,7 @@ static void update_screen_state(struct charger *charger, int64_t now)
if (batt_anim->cur_cycle == batt_anim->num_cycles) {
reset_animation(batt_anim);
charger->next_screen_transition = -1;
+ healthd_board_mode_charger_set_backlight(false);
gr_fb_blank(true);
LOGV("[%" PRId64 "] animation done\n", now);
if (charger->charger_connected)
@@ -406,9 +492,11 @@ static void update_screen_state(struct charger *charger, int64_t now)
batt_anim->capacity = batt_prop->batteryLevel;
}
- /* unblank the screen on first cycle */
- if (batt_anim->cur_cycle == 0)
+ /* unblank the screen on first cycle */
+ if (batt_anim->cur_cycle == 0) {
gr_fb_blank(false);
+ healthd_board_mode_charger_set_backlight(true);
+ }
/* draw the new frame (@ cur_frame) */
redraw_screen(charger);
@@ -508,6 +596,7 @@ static void set_next_key_check(struct charger *charger,
static void process_key(struct charger *charger, int code, int64_t now)
{
+ struct animation *batt_anim = charger->batt_anim;
struct key_state *key = &charger->keys[code];
if (code == KEY_POWER) {
@@ -519,6 +608,8 @@ static void process_key(struct charger *charger, int code, int64_t now)
accordingly. */
if (property_get_bool("ro.enable_boot_charger_mode", false)) {
LOGW("[%" PRId64 "] booting from charger mode\n", now);
+ healthd_board_mode_charger_set_backlight(false);
+ gr_fb_blank(true);
property_set("sys.boot_from_charger_mode", "1");
} else {
if (charger->batt_anim->capacity >= charger->boot_min_cap) {
@@ -534,19 +625,32 @@ static void process_key(struct charger *charger, int code, int64_t now)
* make sure we wake up at the right-ish time to check
*/
set_next_key_check(charger, key, POWER_ON_KEY_TIME);
-
- /* Turn on the display and kick animation on power-key press
- * rather than on key release
- */
- kick_animation(charger->batt_anim);
- request_suspend(false);
}
} else {
- /* if the power key got released, force screen state cycle */
if (key->pending) {
- kick_animation(charger->batt_anim);
+ /* If key is pressed when the animation is not running, kick
+ * the animation and quite suspend; If key is pressed when
+ * the animation is running, turn off the animation and request
+ * suspend.
+ */
+ if (!batt_anim->run) {
+ kick_animation(batt_anim);
+ request_suspend(false);
+ } else {
+ reset_animation(batt_anim);
+ charger->next_screen_transition = -1;
+ healthd_board_mode_charger_set_backlight(false);
+ gr_fb_blank(true);
+ if (charger->charger_connected)
+ request_suspend(true);
+ }
}
}
+ } else {
+ if (key->pending) {
+ request_suspend(false);
+ kick_animation(charger->batt_anim);
+ }
}
key->pending = false;
@@ -555,6 +659,7 @@ static void process_key(struct charger *charger, int code, int64_t now)
static void handle_input_state(struct charger *charger, int64_t now)
{
process_key(charger, KEY_POWER, now);
+ process_key(charger, KEY_HOME, now);
if (charger->next_key_check != -1 && now > charger->next_key_check)
charger->next_key_check = -1;
@@ -562,9 +667,23 @@ static void handle_input_state(struct charger *charger, int64_t now)
static void handle_power_supply_state(struct charger *charger, int64_t now)
{
+ static int old_soc = 0;
+ int soc = 0;
+
if (!charger->have_battery_state)
return;
+ healthd_board_mode_charger_battery_update(batt_prop);
+
+ if (batt_prop && batt_prop->batteryLevel >= 0) {
+ soc = batt_prop->batteryLevel;
+ }
+
+ if (old_soc != soc) {
+ old_soc = soc;
+ set_battery_soc_leds(soc);
+ }
+
if (!charger->charger_connected) {
/* Last cycle would have stopped at the extreme top of battery-icon
@@ -683,6 +802,8 @@ void healthd_mode_charger_init(struct healthd_config* config)
LOGW("--------------- STARTING CHARGER MODE ---------------\n");
+ healthd_board_mode_charger_init();
+
ret = ev_init(input_callback, charger);
if (!ret) {
epollfd = ev_get_epollfd();