import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
-
+import java.util.Timer;
+import java.util.TimerTask;
/**
* <p>BatteryService monitors the charging status, and charge level of the device
mHandler = new Handler(true /*async*/);
mLed = new Led(context, lights);
mBatteryStats = BatteryStatsService.getService();
+ mBatteryLevel = -1; // initialize to an invalid value
mCriticalBatteryLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
"DEVPATH=/devices/virtual/switch/invalid_charger");
}
- // set initial status
- synchronized (mLock) {
- updateLocked();
- }
+ // Some boards have buggy power_supply uevents
+ // Start a timer to update battery level periodically
+ new Timer("BatteryUpdateTimer").schedule(new TimerTask() {
+ @Override
+ public void run() {
+ synchronized (mLock) {
+ updateLocked();
+ }
+ }
+ }, 0, 30000);
}
void systemReady() {
// shut down gracefully if our battery is critically low and we are not powered.
// wait until the system has booted before attempting to display the shutdown dialog.
if (mBatteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {
+ Slog.w(TAG, "shutdownIfNoPower!!!");
mHandler.post(new Runnable() {
@Override
public void run() {
// wait until the system has booted before attempting to display the
// shutdown dialog.
if (mBatteryTemperature > mShutdownBatteryTemperature) {
+ Slog.w(TAG, "shutdownIfOverTemp!!!");
mHandler.post(new Runnable() {
@Override
public void run() {
// Process the new values.
processValuesLocked();
+ if (DEBUG) Slog.v(TAG, "update battery level = " + mBatteryLevel);
}
}
return com.android.internal.R.drawable.stat_sys_battery;
}
} else {
- return com.android.internal.R.drawable.stat_sys_battery_unknown;
+ return mBatteryPresent ?
+ com.android.internal.R.drawable.stat_sys_battery_unknown :
+ com.android.internal.R.drawable.stat_sys_battery_charge;
}
}
String8 batteryHealthPath;
String8 batteryPresentPath;
String8 batteryCapacityPath;
+ String8 batteryChargeNowPath;
+ String8 batteryChargeFullPath;
String8 batteryVoltagePath;
String8 batteryTemperaturePath;
String8 batteryTechnologyPath;
env->SetIntField(obj, fieldID, value);
}
+static void setChargeLevel(JNIEnv* env, jobject obj, jfieldID fieldID) {
+ char buf1[128], buf2[128];
+
+ if (readFromFile(gPaths.batteryChargeNowPath, buf1, 128) > 0 &&
+ readFromFile(gPaths.batteryChargeFullPath, buf2, 128) > 0) {
+ jint value = atoi(buf1) * 100 / atoi(buf2);
+ env->SetIntField(obj, fieldID, value);
+ ALOGV("setChargeLevel value=%d", value);
+ }
+ /*
+ * In some cases the battery path may just disappear a while.
+ * Do not set 0 in such cases to avoid shutdown suddenly.
+ */
+}
+
static PowerSupplyType readPowerSupplyType(const String8& path) {
const int SIZE = 128;
char buf[SIZE];
{
setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent);
- setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);
+ if (gPaths.batteryPresentPath.isEmpty()) {
+ env->SetIntField(obj, gFieldIds.mBatteryLevel, 100);
+ } else {
+ if (gPaths.batteryCapacityPath.isEmpty()) {
+ setChargeLevel(env, obj, gFieldIds.mBatteryLevel);
+ } else {
+ setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);
+ }
+ }
setVoltageField(env, obj, gPaths.batteryVoltagePath, gFieldIds.mBatteryVoltage);
setIntField(env, obj, gPaths.batteryTemperaturePath, gFieldIds.mBatteryTemperature);
default:
ALOGW("%s: Unknown power supply type",
gChargerNames[i].string());
+ break;
}
}
}
}
+ if (i == 0) {
+ /* most likely, we have a PC here */
+ acOnline = true;
+ }
env->SetBooleanField(obj, gFieldIds.mAcOnline, acOnline);
env->SetBooleanField(obj, gFieldIds.mUsbOnline, usbOnline);
gPaths.batteryPresentPath = path;
path.clear();
path.appendFormat("%s/%s/capacity", POWER_SUPPLY_PATH, name);
- if (access(path, R_OK) == 0)
+ if (access(path, R_OK) == 0) {
gPaths.batteryCapacityPath = path;
-
+ } else {
+ path.clear();
+ path.appendFormat("%s/%s/charge_now", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0) {
+ gPaths.batteryChargeNowPath = path;
+ path.clear();
+ path.appendFormat("%s/%s/charge_full", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0) {
+ gPaths.batteryChargeFullPath = path;
+ }
+ } else {
+ path.clear();
+ path.appendFormat("%s/%s/energy_now", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0) {
+ gPaths.batteryChargeNowPath = path;
+ path.clear();
+ path.appendFormat("%s/%s/energy_full", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0) {
+ gPaths.batteryChargeFullPath = path;
+ }
+ }
+ }
+ }
path.clear();
path.appendFormat("%s/%s/voltage_now", POWER_SUPPLY_PATH, name);
if (access(path, R_OK) == 0) {
if (access(path, R_OK) == 0)
gPaths.batteryTechnologyPath = path;
break;
+ default:
+ ALOGW("%s/%s/type is ANDROID_POWER_SUPPLY_TYPE_UNKNOWN?", POWER_SUPPLY_PATH, name);
+ break;
}
}
closedir(dir);
ALOGE_IF(gPaths.batteryStatusPath.isEmpty(), "batteryStatusPath not found");
ALOGE_IF(gPaths.batteryHealthPath.isEmpty(), "batteryHealthPath not found");
ALOGE_IF(gPaths.batteryPresentPath.isEmpty(), "batteryPresentPath not found");
- ALOGE_IF(gPaths.batteryCapacityPath.isEmpty(), "batteryCapacityPath not found");
+ ALOGE_IF(gPaths.batteryCapacityPath.isEmpty() && (gPaths.batteryChargeNowPath.isEmpty() || gPaths.batteryChargeFullPath.isEmpty()), "batteryCapacityPath not found");
ALOGE_IF(gPaths.batteryVoltagePath.isEmpty(), "batteryVoltagePath not found");
ALOGE_IF(gPaths.batteryTemperaturePath.isEmpty(), "batteryTemperaturePath not found");
ALOGE_IF(gPaths.batteryTechnologyPath.isEmpty(), "batteryTechnologyPath not found");