OSDN Git Service

BatteryService: improve battery status support for x86
authorChih-Wei Huang <cwhuang@linux.org.tw>
Tue, 23 Jul 2013 09:10:33 +0000 (17:10 +0800)
committerChih-Wei Huang <cwhuang@linux.org.tw>
Wed, 25 Sep 2013 02:45:43 +0000 (10:45 +0800)
Only set charge level if data is read correctly.
In some cases the battery path may just disappear a while.
Do not set 0 in such cases to avoid shutdown suddenly.

Update the battery status every 30 seconds.

Add more messages for debugging.

services/java/com/android/server/BatteryService.java
services/jni/com_android_server_BatteryService.cpp

index 1f2947d..8ee4b0a 100644 (file)
@@ -44,7 +44,8 @@ import java.io.FileDescriptor;
 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
@@ -150,6 +151,7 @@ public final class BatteryService extends Binder {
         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);
@@ -168,10 +170,16 @@ public final class BatteryService extends Binder {
                     "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() {
@@ -249,6 +257,7 @@ public final class BatteryService extends Binder {
         // 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() {
@@ -268,6 +277,7 @@ public final class BatteryService extends Binder {
         // 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() {
@@ -289,6 +299,7 @@ public final class BatteryService extends Binder {
 
             // Process the new values.
             processValuesLocked();
+            if (DEBUG) Slog.v(TAG, "update battery level = " + mBatteryLevel);
         }
     }
 
@@ -588,7 +599,9 @@ public final class BatteryService extends Binder {
                 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;
         }
     }
 
index 2d2621b..669e3a5 100644 (file)
@@ -76,6 +76,8 @@ struct PowerSupplyPaths {
     String8 batteryHealthPath;
     String8 batteryPresentPath;
     String8 batteryCapacityPath;
+    String8 batteryChargeNowPath;
+    String8 batteryChargeFullPath;
     String8 batteryVoltagePath;
     String8 batteryTemperaturePath;
     String8 batteryTechnologyPath;
@@ -204,6 +206,21 @@ static void setVoltageField(JNIEnv* env, jobject obj, const String8& path, jfiel
     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];
@@ -230,7 +247,15 @@ static void android_server_BatteryService_update(JNIEnv* env, jobject obj)
 {
     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);
     
@@ -278,10 +303,15 @@ static void android_server_BatteryService_update(JNIEnv* env, jobject obj)
                 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);
@@ -339,9 +369,31 @@ int register_android_server_BatteryService(JNIEnv* env)
                     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) {
@@ -371,6 +423,9 @@ int register_android_server_BatteryService(JNIEnv* env)
                 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);
@@ -380,7 +435,7 @@ int register_android_server_BatteryService(JNIEnv* env)
     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");