BatteryService: Add support for new standard battery voltage and temperature attributes.

Plus some cleanup from the previous commit.

Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index eb5c1d1..8e7cadc 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -83,6 +83,8 @@
 };
 static PowerSupplyPaths gPaths;
 
+static int gVoltageDivisor = 1;
+
 static jint getBatteryStatus(const char* status)
 {
     switch (status[0]) {
@@ -132,6 +134,8 @@
 
 static int readFromFile(const char* path, char* buf, size_t size)
 {
+    if (!path)
+        return -1;
     int fd = open(path, O_RDONLY, 0);
     if (fd == -1) {
         LOGE("Could not open '%s'", path);
@@ -177,6 +181,20 @@
     env->SetIntField(obj, fieldID, value);
 }
 
+static void setVoltageField(JNIEnv* env, jobject obj, const char* path, jfieldID fieldID)
+{
+    const int SIZE = 128;
+    char buf[SIZE];
+
+    jint value = 0;
+    if (readFromFile(path, buf, SIZE) > 0) {
+        value = atoi(buf);
+        value /= gVoltageDivisor;
+    }
+    env->SetIntField(obj, fieldID, value);
+}
+
+
 static void android_server_BatteryService_update(JNIEnv* env, jobject obj)
 {
     setBooleanField(env, obj, gPaths.acOnlinePath, gFieldIds.mAcOnline);
@@ -184,7 +202,7 @@
     setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent);
     
     setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);
-    setIntField(env, obj, gPaths.batteryVoltagePath, gFieldIds.mBatteryVoltage);
+    setVoltageField(env, obj, gPaths.batteryVoltagePath, gFieldIds.mBatteryVoltage);
     setIntField(env, obj, gPaths.batteryTemperaturePath, gFieldIds.mBatteryTemperature);
     
     const int SIZE = 128;
@@ -219,42 +237,92 @@
         return -1;
     }
     while ((entry = readdir(dir))) {
+        const char* name = entry->d_name;
+
+        // ignore "." and ".."
+        if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
+            continue;
+        }
+
         char buf[20];
         // Look for "type" file in each subdirectory
-        snprintf(path, sizeof(path), "%s/%s/type", POWER_SUPPLY_PATH, entry->d_name);
+        snprintf(path, sizeof(path), "%s/%s/type", POWER_SUPPLY_PATH, name);
         int length = readFromFile(path, buf, sizeof(buf));
         if (length > 0) {
             if (buf[length - 1] == '\n')
                 buf[length - 1] = 0;
 
             if (strcmp(buf, "Mains") == 0) {
-                snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, entry->d_name);
-                gPaths.acOnlinePath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
+                if (access(path, R_OK) == 0)
+                    gPaths.acOnlinePath = strdup(path);
             }
             else if (strcmp(buf, "USB") == 0) {
-                snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, entry->d_name);
-                gPaths.usbOnlinePath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
+                if (access(path, R_OK) == 0)
+                    gPaths.usbOnlinePath = strdup(path);
             }
             else if (strcmp(buf, "Battery") == 0) {
-                snprintf(path, sizeof(path), "%s/%s/status", POWER_SUPPLY_PATH, entry->d_name);
-                gPaths.batteryStatusPath = strdup(path);
-                snprintf(path, sizeof(path), "%s/%s/health", POWER_SUPPLY_PATH, entry->d_name);
-                gPaths.batteryHealthPath = strdup(path);
-                snprintf(path, sizeof(path), "%s/%s/present", POWER_SUPPLY_PATH, entry->d_name);
-                gPaths.batteryPresentPath = strdup(path);
-                snprintf(path, sizeof(path), "%s/%s/capacity", POWER_SUPPLY_PATH, entry->d_name);
-                gPaths.batteryCapacityPath = strdup(path);
-                snprintf(path, sizeof(path), "%s/%s/batt_vol", POWER_SUPPLY_PATH, entry->d_name);
-                gPaths.batteryVoltagePath = strdup(path);
-                snprintf(path, sizeof(path), "%s/%s/batt_temp", POWER_SUPPLY_PATH, entry->d_name);
-                gPaths.batteryTemperaturePath = strdup(path);
-                snprintf(path, sizeof(path), "%s/%s/technology", POWER_SUPPLY_PATH, entry->d_name);
-                gPaths.batteryTechnologyPath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/status", POWER_SUPPLY_PATH, name);
+                if (access(path, R_OK) == 0)
+                    gPaths.batteryStatusPath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/health", POWER_SUPPLY_PATH, name);
+                if (access(path, R_OK) == 0)
+                    gPaths.batteryHealthPath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/present", POWER_SUPPLY_PATH, name);
+                if (access(path, R_OK) == 0)
+                    gPaths.batteryPresentPath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/capacity", POWER_SUPPLY_PATH, name);
+                if (access(path, R_OK) == 0)
+                    gPaths.batteryCapacityPath = strdup(path);
+
+                snprintf(path, sizeof(path), "%s/%s/voltage_now", POWER_SUPPLY_PATH, name);
+                if (access(path, R_OK) == 0) {
+                    gPaths.batteryVoltagePath = strdup(path);
+                    // voltage_now is in microvolts, not millivolts
+                    gVoltageDivisor = 1000;
+                } else {
+                    snprintf(path, sizeof(path), "%s/%s/batt_vol", POWER_SUPPLY_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        gPaths.batteryVoltagePath = strdup(path);
+                }
+
+                snprintf(path, sizeof(path), "%s/%s/temp", POWER_SUPPLY_PATH, name);
+                if (access(path, R_OK) == 0) {
+                    gPaths.batteryTemperaturePath = strdup(path);
+                } else {
+                    snprintf(path, sizeof(path), "%s/%s/batt_temp", POWER_SUPPLY_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        gPaths.batteryTemperaturePath = strdup(path);
+                }
+
+                snprintf(path, sizeof(path), "%s/%s/technology", POWER_SUPPLY_PATH, name);
+                if (access(path, R_OK) == 0)
+                    gPaths.batteryTechnologyPath = strdup(path);
             }
         }
     }
     closedir(dir);
 
+    if (!gPaths.acOnlinePath)
+        LOGE("acOnlinePath not found");
+    if (!gPaths.usbOnlinePath)
+        LOGE("usbOnlinePath not found");
+    if (!gPaths.batteryStatusPath)
+        LOGE("batteryStatusPath not found");
+    if (!gPaths.batteryHealthPath)
+        LOGE("batteryHealthPath not found");
+    if (!gPaths.batteryPresentPath)
+        LOGE("batteryPresentPath not found");
+    if (!gPaths.batteryCapacityPath)
+        LOGE("batteryCapacityPath not found");
+    if (!gPaths.batteryVoltagePath)
+        LOGE("batteryVoltagePath not found");
+    if (!gPaths.batteryTemperaturePath)
+        LOGE("batteryTemperaturePath not found");
+    if (!gPaths.batteryTechnologyPath)
+        LOGE("batteryTechnologyPath not found");
+
     jclass clazz = env->FindClass("com/android/server/BatteryService");
 
     if (clazz == NULL) {