am bcdb3e73: Merge "Debugging for issue #5180240: Wallpaper continues to consume CPU when screen off"

* commit 'bcdb3e73787f88fe8e45413e1c898dab54212518':
  Debugging for issue #5180240: Wallpaper continues to consume CPU when screen off
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index cdb622c..fbf512c 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -16,6 +16,7 @@
 
 package android.os.storage;
 
+import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -534,6 +535,7 @@
      * @hide
      */
     public String getVolumeState(String mountPoint) {
+         if (mMountService == null) return Environment.MEDIA_REMOVED;
         try {
             return mMountService.getVolumeState(mountPoint);
         } catch (RemoteException e) {
@@ -547,6 +549,7 @@
      * @hide
      */
     public StorageVolume[] getVolumeList() {
+        if (mMountService == null) return new StorageVolume[0];
         try {
             Parcelable[] list = mMountService.getVolumeList();
             if (list == null) return new StorageVolume[0];
diff --git a/core/jni/android_view_Display.cpp b/core/jni/android_view_Display.cpp
index 5e668b9..0b7af85 100644
--- a/core/jni/android_view_Display.cpp
+++ b/core/jni/android_view_Display.cpp
@@ -28,6 +28,7 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 #include <utils/Log.h>
+#include <cutils/properties.h>
 
 // ----------------------------------------------------------------------------
 
@@ -44,6 +45,7 @@
     jfieldID ydpi;
 };
 static offsets_t offsets;
+static bool headless = false;
 
 // ----------------------------------------------------------------------------
 
@@ -51,10 +53,19 @@
         JNIEnv* env, jobject clazz, jint dpy)
 {
     DisplayInfo info;
-    status_t err = SurfaceComposerClient::getDisplayInfo(DisplayID(dpy), &info);
-    if (err < 0) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-        return;
+    if (headless) {
+        // initialize dummy display with reasonable values
+        info.pixelFormatInfo.format = 1; // RGB_8888
+        info.fps = 60;
+        info.density = 160;
+        info.xdpi = 160;
+        info.ydpi = 160;
+    } else {
+        status_t err = SurfaceComposerClient::getDisplayInfo(DisplayID(dpy), &info);
+        if (err < 0) {
+            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+            return;
+        }
     }
     env->SetIntField(clazz, offsets.pixelFormat,info.pixelFormatInfo.format);
     env->SetFloatField(clazz, offsets.fps,      info.fps);
@@ -66,6 +77,7 @@
 static jint android_view_Display_getRawWidth(
         JNIEnv* env, jobject clazz)
 {
+    if (headless) return 640;
     DisplayID dpy = env->GetIntField(clazz, offsets.display);
     return SurfaceComposerClient::getDisplayWidth(dpy);
 }
@@ -73,6 +85,7 @@
 static jint android_view_Display_getRawHeight(
         JNIEnv* env, jobject clazz)
 {
+    if (headless) return 480;
     DisplayID dpy = env->GetIntField(clazz, offsets.display);
     return SurfaceComposerClient::getDisplayHeight(dpy);
 }
@@ -80,6 +93,7 @@
 static jint android_view_Display_getOrientation(
         JNIEnv* env, jobject clazz)
 {
+    if (headless) return 0; // Surface.ROTATION_0
     DisplayID dpy = env->GetIntField(clazz, offsets.display);
     return SurfaceComposerClient::getDisplayOrientation(dpy);
 }
@@ -87,6 +101,7 @@
 static jint android_view_Display_getDisplayCount(
         JNIEnv* env, jclass clazz)
 {
+    if (headless) return 1;
     return SurfaceComposerClient::getNumberOfDisplays();
 }
 
@@ -113,6 +128,12 @@
 
 void nativeClassInit(JNIEnv* env, jclass clazz)
 {
+    char value[PROPERTY_VALUE_MAX];
+
+    property_get("ro.config.headless", value, "0");
+    if (strcmp(value, "1") == 0)
+        headless = true;
+
     offsets.display     = env->GetFieldID(clazz, "mDisplay", "I");
     offsets.pixelFormat = env->GetFieldID(clazz, "mPixelFormat", "I");
     offsets.fps         = env->GetFieldID(clazz, "mRefreshRate", "F");
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 1d5fbc0a..1871d68e 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -610,7 +610,7 @@
         if (mGlobalActions == null) {
             mGlobalActions = new GlobalActions(mContext);
         }
-        final boolean keyguardShowing = mKeyguardMediator.isShowingAndNotHidden();
+        final boolean keyguardShowing = keyguardIsShowingTq();
         mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
         if (keyguardShowing) {
             // since it took two seconds of long press to bring this up,
@@ -693,7 +693,10 @@
         mContext = context;
         mWindowManager = windowManager;
         mPowerManager = powerManager;
-        mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
+        if ("0".equals(SystemProperties.get("ro.config.headless", "0"))) {
+            // don't create KeyguardViewMediator if headless
+            mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
+        }
         mHandler = new Handler();
         mOrientationListener = new MyOrientationListener(mContext);
         SettingsObserver settingsObserver = new SettingsObserver(mHandler);
@@ -1645,7 +1648,7 @@
      * given the situation with the keyguard.
      */
     void launchHomeFromHotKey() {
-        if (mKeyguardMediator.isShowingAndNotHidden()) {
+        if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {
             // don't launch home if keyguard showing
         } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
             // when in keyguard restricted mode, must first verify unlock
@@ -2286,6 +2289,9 @@
 
     /** {@inheritDoc} */
     public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
+        // do nothing if headless
+        if (mKeyguardMediator == null) return;
+
         // lid changed state
         mLidOpen = lidOpen ? LID_OPEN : LID_CLOSED;
         boolean awakeNow = mKeyguardMediator.doLidChangeTq(lidOpen);
@@ -2486,9 +2492,10 @@
         // the same as if it were open and in front.
         // This will prevent any keys other than the power button from waking the screen
         // when the keyguard is hidden by another activity.
-        final boolean keyguardActive = (isScreenOn ?
-                                        mKeyguardMediator.isShowingAndNotHidden() :
-                                        mKeyguardMediator.isShowing());
+        final boolean keyguardActive = (mKeyguardMediator == null ? false :
+                                            (isScreenOn ?
+                                                mKeyguardMediator.isShowingAndNotHidden() :
+                                                mKeyguardMediator.isShowing()));
 
         if (false) {
             Log.d(TAG, "interceptKeyTq keycode=" + keyCode
@@ -2742,7 +2749,7 @@
         final boolean isWakeMotion = (policyFlags
                 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
         if (isWakeMotion) {
-            if (mKeyguardMediator.isShowing()) {
+            if (mKeyguardMediator != null && mKeyguardMediator.isShowing()) {
                 // If the keyguard is showing, let it decide what to do with the wake motion.
                 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
             } else {
@@ -2797,7 +2804,9 @@
     /** {@inheritDoc} */
     public void screenTurnedOff(int why) {
         EventLog.writeEvent(70000, 0);
-        mKeyguardMediator.onScreenTurnedOff(why);
+        if (mKeyguardMediator != null) {
+            mKeyguardMediator.onScreenTurnedOff(why);
+        }
         synchronized (mLock) {
             mScreenOn = false;
             updateOrientationListenerLp();
@@ -2809,7 +2818,9 @@
     /** {@inheritDoc} */
     public void screenTurnedOn() {
         EventLog.writeEvent(70000, 1);
-        mKeyguardMediator.onScreenTurnedOn();
+        if (mKeyguardMediator != null) {
+            mKeyguardMediator.onScreenTurnedOn();
+        }
         synchronized (mLock) {
             mScreenOn = true;
             updateOrientationListenerLp();
@@ -2825,15 +2836,20 @@
     
     /** {@inheritDoc} */
     public void enableKeyguard(boolean enabled) {
-        mKeyguardMediator.setKeyguardEnabled(enabled);
+        if (mKeyguardMediator != null) {
+            mKeyguardMediator.setKeyguardEnabled(enabled);
+        }
     }
 
     /** {@inheritDoc} */
     public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
-        mKeyguardMediator.verifyUnlock(callback);
+        if (mKeyguardMediator != null) {
+            mKeyguardMediator.verifyUnlock(callback);
+        }
     }
 
     private boolean keyguardIsShowingTq() {
+        if (mKeyguardMediator == null) return false;
         return mKeyguardMediator.isShowingAndNotHidden();
     }
 
@@ -2845,11 +2861,13 @@
 
     /** {@inheritDoc} */
     public boolean isKeyguardSecure() {
+        if (mKeyguardMediator == null) return false;
         return mKeyguardMediator.isSecure();
     }
 
     /** {@inheritDoc} */
     public boolean inKeyguardRestrictedKeyInputMode() {
+        if (mKeyguardMediator == null) return false;
         return mKeyguardMediator.isInputRestricted();
     }
 
@@ -3066,8 +3084,10 @@
     
     /** {@inheritDoc} */
     public void systemReady() {
-        // tell the keyguard
-        mKeyguardMediator.onSystemReady();
+        if (mKeyguardMediator != null) {
+            // tell the keyguard
+            mKeyguardMediator.onSystemReady();
+        }
         android.os.SystemProperties.set("dev.bootcomplete", "1"); 
         synchronized (mLock) {
             updateOrientationListenerLp();
@@ -3199,7 +3219,9 @@
         public void run() {
             synchronized (this) {
                 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
-                mKeyguardMediator.doKeyguardTimeout();
+                if (mKeyguardMediator != null) {
+                    mKeyguardMediator.doKeyguardTimeout();
+                }
                 mLockScreenTimerActive = false;
             }
         }
@@ -3207,7 +3229,8 @@
 
     private void updateLockScreenTimeout() {
         synchronized (mScreenLockTimeout) {
-            boolean enable = (mAllowLockscreenWhenOn && mScreenOn && mKeyguardMediator.isSecure());
+            boolean enable = (mAllowLockscreenWhenOn && mScreenOn &&
+                    mKeyguardMediator != null && mKeyguardMediator.isSecure());
             if (mLockScreenTimerActive != enable) {
                 if (enable) {
                     if (localLOGV) Log.v(TAG, "setting lockscreen timer");
@@ -3400,7 +3423,7 @@
 
     public void screenOnStoppedLw() {
         if (mPowerManager.isScreenOn()) {
-            if (!mKeyguardMediator.isShowingAndNotHidden()) {
+            if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
                 long curTime = SystemClock.uptimeMillis();
                 mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
             }
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index d80a2cd..532eca2 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -50,6 +50,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.WorkSource;
 import android.provider.Settings.SettingNotFoundException;
 import android.provider.Settings;
@@ -158,6 +159,7 @@
 
     private boolean mDoneBooting = false;
     private boolean mBootCompleted = false;
+    private boolean mHeadless = false;
     private int mStayOnConditions = 0;
     private final int[] mBroadcastQueue = new int[] { -1, -1, -1 };
     private final int[] mBroadcastWhy = new int[3];
@@ -503,6 +505,7 @@
         mButtonLight = lights.getLight(LightsService.LIGHT_ID_BUTTONS);
         mKeyboardLight = lights.getLight(LightsService.LIGHT_ID_KEYBOARD);
         mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION);
+        mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
 
         nativeInit();
         synchronized (mLocks) {
@@ -1768,9 +1771,11 @@
     }
     
     private void updateNativePowerStateLocked() {
-        nativeSetPowerState(
-                (mPowerState & SCREEN_ON_BIT) != 0,
-                (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT);
+        if (!mHeadless) {
+            nativeSetPowerState(
+                    (mPowerState & SCREEN_ON_BIT) != 0,
+                    (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT);
+        }
     }
 
     private int screenOffFinishedAnimatingLocked(int reason) {
@@ -2059,7 +2064,9 @@
             } else {
                 synchronized (mLocks) {
                     // we're turning off
-                    final boolean animate = animating && targetValue == Power.BRIGHTNESS_OFF;
+                    final boolean animate = animating
+                            && targetValue == Power.BRIGHTNESS_OFF
+                            && !mHeadless;
                     if (animate) {
                         // It's pretty scary to hold mLocks for this long, and we should
                         // redesign this, but it works for now.
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e6f92a5..858f165 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -106,6 +106,7 @@
         String factoryTestStr = SystemProperties.get("ro.factorytest");
         int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
                 : Integer.parseInt(factoryTestStr);
+        final boolean headless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
 
         LightsService lights = null;
         PowerManagerService power = null;
@@ -376,15 +377,17 @@
                 reportWtf("starting ThrottleService", e);
             }
 
-            try {
-                /*
-                 * NotificationManagerService is dependant on MountService,
-                 * (for media / usb notifications) so we must start MountService first.
-                 */
-                Slog.i(TAG, "Mount Service");
-                ServiceManager.addService("mount", new MountService(context));
-            } catch (Throwable e) {
-                reportWtf("starting Mount Service", e);
+            if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) {
+                try {
+                    /*
+                     * NotificationManagerService is dependant on MountService,
+                     * (for media / usb notifications) so we must start MountService first.
+                     */
+                    Slog.i(TAG, "Mount Service");
+                    ServiceManager.addService("mount", new MountService(context));
+                } catch (Throwable e) {
+                    reportWtf("starting Mount Service", e);
+                }
             }
 
             try {
@@ -438,17 +441,21 @@
 
             try {
                 Slog.i(TAG, "Wallpaper Service");
-                wallpaper = new WallpaperManagerService(context);
-                ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
+                if (!headless) {
+                    wallpaper = new WallpaperManagerService(context);
+                    ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
+                }
             } catch (Throwable e) {
                 reportWtf("starting Wallpaper Service", e);
             }
 
-            try {
-                Slog.i(TAG, "Audio Service");
-                ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context));
-            } catch (Throwable e) {
-                reportWtf("starting Audio Service", e);
+            if (!"0".equals(SystemProperties.get("system_init.startaudioservice"))) {
+                try {
+                    Slog.i(TAG, "Audio Service");
+                    ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context));
+                } catch (Throwable e) {
+                    reportWtf("starting Audio Service", e);
+                }
             }
 
             try {
@@ -623,7 +630,7 @@
             public void run() {
                 Slog.i(TAG, "Making services ready");
 
-                startSystemUi(contextF);
+                if (!headless) startSystemUi(contextF);
                 try {
                     if (batteryF != null) batteryF.systemReady();
                 } catch (Throwable e) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index b817598..e40a8d8 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -257,7 +257,9 @@
     static final String[] EMPTY_STRING_ARRAY = new String[0];
 
     public ActivityStack mMainStack;
-    
+
+    private final boolean mHeadless;
+
     /**
      * Description of a request to start a new activity, which has been held
      * due to app switches being disabled.
@@ -1366,6 +1368,7 @@
         
         mUsageStatsService = new UsageStatsService(new File(
                 systemDir, "usagestats").toString());
+        mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
 
         GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
             ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
@@ -1901,6 +1904,8 @@
     }
 
     boolean startHomeActivityLocked() {
+        if (mHeadless) return false;
+
         if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
                 && mTopAction == null) {
             // We are running in factory test mode, but unable to find
@@ -3631,7 +3636,9 @@
             if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
                     && processName.equals(hr.processName)) {
                 try {
-                    if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
+                    if (mHeadless) {
+                        Slog.e(TAG, "Starting activities not supported on headless device: " + hr);
+                    } else if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
                         didSomething = true;
                     }
                 } catch (Exception e) {
@@ -12646,6 +12653,9 @@
      */
     public boolean updateConfigurationLocked(Configuration values,
             ActivityRecord starting, boolean persistent) {
+        // do nothing if we are headless
+        if (mHeadless) return true;
+
         int changes = 0;
         
         boolean kept = true;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index dc5555e..1113386 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -245,6 +245,7 @@
 
     private static final String SYSTEM_SECURE = "ro.secure";
     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
+    private static final String SYSTEM_HEADLESS = "ro.config.headless";
 
     /**
      * Condition waited on by {@link #reenableKeyguard} to know the call to
@@ -254,6 +255,8 @@
      */
     private boolean mKeyguardDisabled = false;
 
+    private final boolean mHeadless;
+
     private static final int ALLOW_DISABLE_YES = 1;
     private static final int ALLOW_DISABLE_NO = 0;
     private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
@@ -718,6 +721,7 @@
         mHaveInputMethods = haveInputMethods;
         mLimitedAlphaCompositing = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_sf_limitedAlpha);
+        mHeadless = "1".equals(SystemProperties.get(SYSTEM_HEADLESS, "0"));
 
         mPowerManager = pm;
         mPowerManager.setPolicy(mPolicy);
@@ -4788,6 +4792,8 @@
     // TODO: more accounting of which pid(s) turned it on, keep count,
     // only allow disables from pids which have count on, etc.
     public void showStrictModeViolation(boolean on) {
+        if (mHeadless) return;
+
         int pid = Binder.getCallingPid();
         synchronized(mWindowMap) {
             // Ignoring requests to enable the red border from clients
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index b9f2c1f..87ca3bf 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -233,75 +233,75 @@
     DIR* dir = opendir(POWER_SUPPLY_PATH);
     if (dir == NULL) {
         LOGE("Could not open %s\n", POWER_SUPPLY_PATH);
-        return -1;
-    }
-    while ((entry = readdir(dir))) {
-        const char* name = entry->d_name;
+    } else {
+        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, 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, name);
-                if (access(path, R_OK) == 0)
-                    gPaths.acOnlinePath = strdup(path);
+            // ignore "." and ".."
+            if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
+                continue;
             }
-            else if (strcmp(buf, "USB") == 0) {
-                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, 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);
+            char buf[20];
+            // Look for "type" file in each subdirectory
+            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, 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, 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, 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)
+                    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);
+                    snprintf(path, sizeof(path), "%s/%s/technology", POWER_SUPPLY_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        gPaths.batteryTechnologyPath = strdup(path);
+                }
             }
         }
+        closedir(dir);
     }
-    closedir(dir);
 
     if (!gPaths.acOnlinePath)
         LOGE("acOnlinePath not found");