BatteryService use IBatteryProperties interfaces, drop JNI

IBatteryPropertiesListener binder interface to deliver notifications of
changed battery/power status from healthd system health daemon.  healthd
watches uevents from power_supply.

Change-Id: I1ab38622baf28356a6627fe2354b77e2ef99d838
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 2d42cd61..457539f 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -26,9 +26,12 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.BatteryManager;
+import android.os.BatteryProperties;
 import android.os.Binder;
 import android.os.FileUtils;
 import android.os.Handler;
+import android.os.IBatteryPropertiesListener;
+import android.os.IBatteryPropertiesRegistrar;
 import android.os.IBinder;
 import android.os.DropBoxManager;
 import android.os.RemoteException;
@@ -102,20 +105,8 @@
 
     private final Object mLock = new Object();
 
-    /* Begin native fields: All of these fields are set by native code. */
-    private boolean mAcOnline;
-    private boolean mUsbOnline;
-    private boolean mWirelessOnline;
-    private int mBatteryStatus;
-    private int mBatteryHealth;
-    private boolean mBatteryPresent;
-    private int mBatteryLevel;
-    private int mBatteryVoltage;
-    private int mBatteryTemperature;
-    private String mBatteryTechnology;
+    private BatteryProperties mBatteryProps;
     private boolean mBatteryLevelCritical;
-    /* End native fields. */
-
     private int mLastBatteryStatus;
     private int mLastBatteryHealth;
     private boolean mLastBatteryPresent;
@@ -143,7 +134,8 @@
 
     private boolean mSentLowBatteryBroadcast = false;
 
-    private native void native_update();
+    private BatteryListener mBatteryPropertiesListener;
+    private IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
 
     public BatteryService(Context context, LightsService lights) {
         mContext = context;
@@ -160,17 +152,21 @@
         mShutdownBatteryTemperature = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_shutdownBatteryTemperature);
 
-        mPowerSupplyObserver.startObserving("SUBSYSTEM=power_supply");
-
         // watch for invalid charger messages if the invalid_charger switch exists
         if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
             mInvalidChargerObserver.startObserving(
                     "DEVPATH=/devices/virtual/switch/invalid_charger");
         }
 
-        // set initial status
-        synchronized (mLock) {
-            updateLocked();
+        mBatteryPropertiesListener = new BatteryListener();
+
+        IBinder b = ServiceManager.getService("batterypropreg");
+        mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(b);
+
+        try {
+            mBatteryPropertiesRegistrar.registerListener(mBatteryPropertiesListener);
+        } catch (RemoteException e) {
+            // Should never happen.
         }
     }
 
@@ -194,16 +190,16 @@
     private boolean isPoweredLocked(int plugTypeSet) {
         // assume we are powered if battery state is unknown so
         // the "stay on while plugged in" option will work.
-        if (mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
+        if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
             return true;
         }
-        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mAcOnline) {
+        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mBatteryProps.chargerAcOnline) {
             return true;
         }
-        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mUsbOnline) {
+        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mBatteryProps.chargerUsbOnline) {
             return true;
         }
-        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mWirelessOnline) {
+        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mBatteryProps.chargerWirelessOnline) {
             return true;
         }
         return false;
@@ -223,7 +219,7 @@
      */
     public int getBatteryLevel() {
         synchronized (mLock) {
-            return mBatteryLevel;
+            return mBatteryProps.batteryLevel;
         }
     }
 
@@ -232,7 +228,7 @@
      */
     public boolean isBatteryLow() {
         synchronized (mLock) {
-            return mBatteryPresent && mBatteryLevel <= mLowBatteryWarningLevel;
+            return mBatteryProps.batteryPresent && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel;
         }
     }
 
@@ -248,7 +244,7 @@
     private void shutdownIfNoPowerLocked() {
         // 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)) {
+        if (mBatteryProps.batteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -267,7 +263,7 @@
         // shut down gracefully if temperature is too high (> 68.0C by default)
         // wait until the system has booted before attempting to display the
         // shutdown dialog.
-        if (mBatteryTemperature > mShutdownBatteryTemperature) {
+        if (mBatteryProps.batteryTemperature > mShutdownBatteryTemperature) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -282,13 +278,13 @@
         }
     }
 
-    private void updateLocked() {
-        if (!mUpdatesStopped) {
-            // Update the values of mAcOnline, et. all.
-            native_update();
-
-            // Process the new values.
-            processValuesLocked();
+    private void update(BatteryProperties props) {
+        synchronized (mLock) {
+            if (!mUpdatesStopped) {
+                mBatteryProps = props;
+                // Process the new values.
+                processValuesLocked();
+            }
         }
     }
 
@@ -296,12 +292,12 @@
         boolean logOutlier = false;
         long dischargeDuration = 0;
 
-        mBatteryLevelCritical = (mBatteryLevel <= mCriticalBatteryLevel);
-        if (mAcOnline) {
+        mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel);
+        if (mBatteryProps.chargerAcOnline) {
             mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
-        } else if (mUsbOnline) {
+        } else if (mBatteryProps.chargerUsbOnline) {
             mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
-        } else if (mWirelessOnline) {
+        } else if (mBatteryProps.chargerWirelessOnline) {
             mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
         } else {
             mPlugType = BATTERY_PLUGGED_NONE;
@@ -309,25 +305,25 @@
 
         if (DEBUG) {
             Slog.d(TAG, "Processing new values: "
-                    + "mAcOnline=" + mAcOnline
-                    + ", mUsbOnline=" + mUsbOnline
-                    + ", mWirelessOnline=" + mWirelessOnline
-                    + ", mBatteryStatus=" + mBatteryStatus
-                    + ", mBatteryHealth=" + mBatteryHealth
-                    + ", mBatteryPresent=" + mBatteryPresent
-                    + ", mBatteryLevel=" + mBatteryLevel
-                    + ", mBatteryTechnology=" + mBatteryTechnology
-                    + ", mBatteryVoltage=" + mBatteryVoltage
-                    + ", mBatteryTemperature=" + mBatteryTemperature
+                    + "chargerAcOnline=" + mBatteryProps.chargerAcOnline
+                    + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline
+                    + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline
+                    + ", batteryStatus=" + mBatteryProps.batteryStatus
+                    + ", batteryHealth=" + mBatteryProps.batteryHealth
+                    + ", batteryPresent=" + mBatteryProps.batteryPresent
+                    + ", batteryLevel=" + mBatteryProps.batteryLevel
+                    + ", batteryTechnology=" + mBatteryProps.batteryTechnology
+                    + ", batteryVoltage=" + mBatteryProps.batteryVoltage
+                    + ", batteryTemperature=" + mBatteryProps.batteryTemperature
                     + ", mBatteryLevelCritical=" + mBatteryLevelCritical
                     + ", mPlugType=" + mPlugType);
         }
 
         // Let the battery stats keep track of the current level.
         try {
-            mBatteryStats.setBatteryState(mBatteryStatus, mBatteryHealth,
-                    mPlugType, mBatteryLevel, mBatteryTemperature,
-                    mBatteryVoltage);
+            mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
+                    mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
+                    mBatteryProps.batteryVoltage);
         } catch (RemoteException e) {
             // Should never happen.
         }
@@ -335,13 +331,13 @@
         shutdownIfNoPowerLocked();
         shutdownIfOverTempLocked();
 
-        if (mBatteryStatus != mLastBatteryStatus ||
-                mBatteryHealth != mLastBatteryHealth ||
-                mBatteryPresent != mLastBatteryPresent ||
-                mBatteryLevel != mLastBatteryLevel ||
+        if (mBatteryProps.batteryStatus != mLastBatteryStatus ||
+                mBatteryProps.batteryHealth != mLastBatteryHealth ||
+                mBatteryProps.batteryPresent != mLastBatteryPresent ||
+                mBatteryProps.batteryLevel != mLastBatteryLevel ||
                 mPlugType != mLastPlugType ||
-                mBatteryVoltage != mLastBatteryVoltage ||
-                mBatteryTemperature != mLastBatteryTemperature ||
+                mBatteryProps.batteryVoltage != mLastBatteryVoltage ||
+                mBatteryProps.batteryTemperature != mLastBatteryTemperature ||
                 mInvalidCharger != mLastInvalidCharger) {
 
             if (mPlugType != mLastPlugType) {
@@ -350,33 +346,33 @@
 
                     // There's no value in this data unless we've discharged at least once and the
                     // battery level has changed; so don't log until it does.
-                    if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryLevel) {
+                    if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryProps.batteryLevel) {
                         dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
                         logOutlier = true;
                         EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,
-                                mDischargeStartLevel, mBatteryLevel);
+                                mDischargeStartLevel, mBatteryProps.batteryLevel);
                         // make sure we see a discharge event before logging again
                         mDischargeStartTime = 0;
                     }
                 } else if (mPlugType == BATTERY_PLUGGED_NONE) {
                     // charging -> discharging or we just powered up
                     mDischargeStartTime = SystemClock.elapsedRealtime();
-                    mDischargeStartLevel = mBatteryLevel;
+                    mDischargeStartLevel = mBatteryProps.batteryLevel;
                 }
             }
-            if (mBatteryStatus != mLastBatteryStatus ||
-                    mBatteryHealth != mLastBatteryHealth ||
-                    mBatteryPresent != mLastBatteryPresent ||
+            if (mBatteryProps.batteryStatus != mLastBatteryStatus ||
+                    mBatteryProps.batteryHealth != mLastBatteryHealth ||
+                    mBatteryProps.batteryPresent != mLastBatteryPresent ||
                     mPlugType != mLastPlugType) {
                 EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
-                        mBatteryStatus, mBatteryHealth, mBatteryPresent ? 1 : 0,
-                        mPlugType, mBatteryTechnology);
+                        mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0,
+                        mPlugType, mBatteryProps.batteryTechnology);
             }
-            if (mBatteryLevel != mLastBatteryLevel) {
+            if (mBatteryProps.batteryLevel != mLastBatteryLevel) {
                 // Don't do this just from voltage or temperature changes, that is
                 // too noisy.
                 EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
-                        mBatteryLevel, mBatteryVoltage, mBatteryTemperature);
+                        mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature);
             }
             if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
                     mPlugType == BATTERY_PLUGGED_NONE) {
@@ -396,8 +392,8 @@
              *   (becomes <= mLowBatteryWarningLevel).
              */
             final boolean sendBatteryLow = !plugged
-                    && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
-                    && mBatteryLevel <= mLowBatteryWarningLevel
+                    && mBatteryProps.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
+                    && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel
                     && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);
 
             sendIntentLocked();
@@ -456,13 +452,13 @@
                 logOutlierLocked(dischargeDuration);
             }
 
-            mLastBatteryStatus = mBatteryStatus;
-            mLastBatteryHealth = mBatteryHealth;
-            mLastBatteryPresent = mBatteryPresent;
-            mLastBatteryLevel = mBatteryLevel;
+            mLastBatteryStatus = mBatteryProps.batteryStatus;
+            mLastBatteryHealth = mBatteryProps.batteryHealth;
+            mLastBatteryPresent = mBatteryProps.batteryPresent;
+            mLastBatteryLevel = mBatteryProps.batteryLevel;
             mLastPlugType = mPlugType;
-            mLastBatteryVoltage = mBatteryVoltage;
-            mLastBatteryTemperature = mBatteryTemperature;
+            mLastBatteryVoltage = mBatteryProps.batteryVoltage;
+            mLastBatteryTemperature = mBatteryProps.batteryTemperature;
             mLastBatteryLevelCritical = mBatteryLevelCritical;
             mLastInvalidCharger = mInvalidCharger;
         }
@@ -474,29 +470,29 @@
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
 
-        int icon = getIconLocked(mBatteryLevel);
+        int icon = getIconLocked(mBatteryProps.batteryLevel);
 
-        intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryStatus);
-        intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryHealth);
-        intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryPresent);
-        intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryLevel);
+        intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
+        intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth);
+        intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryProps.batteryPresent);
+        intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryProps.batteryLevel);
         intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
         intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);
         intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
-        intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryVoltage);
-        intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryTemperature);
-        intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryTechnology);
+        intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryProps.batteryVoltage);
+        intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryProps.batteryTemperature);
+        intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryProps.batteryTechnology);
         intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
 
         if (DEBUG) {
-            Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED.  level:" + mBatteryLevel +
-                    ", scale:" + BATTERY_SCALE + ", status:" + mBatteryStatus +
-                    ", health:" + mBatteryHealth +  ", present:" + mBatteryPresent +
-                    ", voltage: " + mBatteryVoltage +
-                    ", temperature: " + mBatteryTemperature +
-                    ", technology: " + mBatteryTechnology +
-                    ", AC powered:" + mAcOnline + ", USB powered:" + mUsbOnline +
-                    ", Wireless powered:" + mWirelessOnline +
+            Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED.  level:" + mBatteryProps.batteryLevel +
+                    ", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus +
+                    ", health:" + mBatteryProps.batteryHealth +  ", present:" + mBatteryProps.batteryPresent +
+                    ", voltage: " + mBatteryProps.batteryVoltage +
+                    ", temperature: " + mBatteryProps.batteryTemperature +
+                    ", technology: " + mBatteryProps.batteryTechnology +
+                    ", AC powered:" + mBatteryProps.chargerAcOnline + ", USB powered:" + mBatteryProps.chargerUsbOnline +
+                    ", Wireless powered:" + mBatteryProps.chargerWirelessOnline +
                     ", icon:" + icon  + ", invalid charger:" + mInvalidCharger);
         }
 
@@ -558,14 +554,14 @@
                 long durationThreshold = Long.parseLong(durationThresholdString);
                 int dischargeThreshold = Integer.parseInt(dischargeThresholdString);
                 if (duration <= durationThreshold &&
-                        mDischargeStartLevel - mBatteryLevel >= dischargeThreshold) {
+                        mDischargeStartLevel - mBatteryProps.batteryLevel >= dischargeThreshold) {
                     // If the discharge cycle is bad enough we want to know about it.
                     logBatteryStatsLocked();
                 }
                 if (DEBUG) Slog.v(TAG, "duration threshold: " + durationThreshold +
                         " discharge threshold: " + dischargeThreshold);
                 if (DEBUG) Slog.v(TAG, "duration: " + duration + " discharge: " +
-                        (mDischargeStartLevel - mBatteryLevel));
+                        (mDischargeStartLevel - mBatteryProps.batteryLevel));
             } catch (NumberFormatException e) {
                 Slog.e(TAG, "Invalid DischargeThresholds GService string: " +
                         durationThresholdString + " or " + dischargeThresholdString);
@@ -575,14 +571,14 @@
     }
 
     private int getIconLocked(int level) {
-        if (mBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
+        if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
             return com.android.internal.R.drawable.stat_sys_battery_charge;
-        } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
+        } else if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) {
             return com.android.internal.R.drawable.stat_sys_battery;
-        } else if (mBatteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING
-                || mBatteryStatus == BatteryManager.BATTERY_STATUS_FULL) {
+        } else if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING
+                || mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_FULL) {
             if (isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)
-                    && mBatteryLevel >= 100) {
+                    && mBatteryProps.batteryLevel >= 100) {
                 return com.android.internal.R.drawable.stat_sys_battery_charge;
             } else {
                 return com.android.internal.R.drawable.stat_sys_battery;
@@ -609,32 +605,32 @@
                 if (mUpdatesStopped) {
                     pw.println("  (UPDATES STOPPED -- use 'reset' to restart)");
                 }
-                pw.println("  AC powered: " + mAcOnline);
-                pw.println("  USB powered: " + mUsbOnline);
-                pw.println("  Wireless powered: " + mWirelessOnline);
-                pw.println("  status: " + mBatteryStatus);
-                pw.println("  health: " + mBatteryHealth);
-                pw.println("  present: " + mBatteryPresent);
-                pw.println("  level: " + mBatteryLevel);
+                pw.println("  AC powered: " + mBatteryProps.chargerAcOnline);
+                pw.println("  USB powered: " + mBatteryProps.chargerUsbOnline);
+                pw.println("  Wireless powered: " + mBatteryProps.chargerWirelessOnline);
+                pw.println("  status: " + mBatteryProps.batteryStatus);
+                pw.println("  health: " + mBatteryProps.batteryHealth);
+                pw.println("  present: " + mBatteryProps.batteryPresent);
+                pw.println("  level: " + mBatteryProps.batteryLevel);
                 pw.println("  scale: " + BATTERY_SCALE);
-                pw.println("  voltage:" + mBatteryVoltage);
-                pw.println("  temperature: " + mBatteryTemperature);
-                pw.println("  technology: " + mBatteryTechnology);
+                pw.println("  voltage:" + mBatteryProps.batteryVoltage);
+                pw.println("  temperature: " + mBatteryProps.batteryTemperature);
+                pw.println("  technology: " + mBatteryProps.batteryTechnology);
             } else if (args.length == 3 && "set".equals(args[0])) {
                 String key = args[1];
                 String value = args[2];
                 try {
                     boolean update = true;
                     if ("ac".equals(key)) {
-                        mAcOnline = Integer.parseInt(value) != 0;
+                        mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
                     } else if ("usb".equals(key)) {
-                        mUsbOnline = Integer.parseInt(value) != 0;
+                        mBatteryProps.chargerUsbOnline = Integer.parseInt(value) != 0;
                     } else if ("wireless".equals(key)) {
-                        mWirelessOnline = Integer.parseInt(value) != 0;
+                        mBatteryProps.chargerWirelessOnline = Integer.parseInt(value) != 0;
                     } else if ("status".equals(key)) {
-                        mBatteryStatus = Integer.parseInt(value);
+                        mBatteryProps.batteryStatus = Integer.parseInt(value);
                     } else if ("level".equals(key)) {
-                        mBatteryLevel = Integer.parseInt(value);
+                        mBatteryProps.batteryLevel = Integer.parseInt(value);
                     } else if ("invalid".equals(key)) {
                         mInvalidCharger = Integer.parseInt(value);
                     } else {
@@ -657,7 +653,6 @@
                 long ident = Binder.clearCallingIdentity();
                 try {
                     mUpdatesStopped = false;
-                    updateLocked();
                 } finally {
                     Binder.restoreCallingIdentity(ident);
                 }
@@ -669,15 +664,6 @@
         }
     }
 
-    private final UEventObserver mPowerSupplyObserver = new UEventObserver() {
-        @Override
-        public void onUEvent(UEventObserver.UEvent event) {
-            synchronized (mLock) {
-                updateLocked();
-            }
-        }
-    };
-
     private final UEventObserver mInvalidChargerObserver = new UEventObserver() {
         @Override
         public void onUEvent(UEventObserver.UEvent event) {
@@ -685,7 +671,6 @@
             synchronized (mLock) {
                 if (mInvalidCharger != invalidCharger) {
                     mInvalidCharger = invalidCharger;
-                    updateLocked();
                 }
             }
         }
@@ -719,8 +704,8 @@
          * Synchronize on BatteryService.
          */
         public void updateLightsLocked() {
-            final int level = mBatteryLevel;
-            final int status = mBatteryStatus;
+            final int level = mBatteryProps.batteryLevel;
+            final int status = mBatteryProps.batteryStatus;
             if (level < mLowBatteryWarningLevel) {
                 if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
                     // Solid red when battery is charging
@@ -745,4 +730,10 @@
             }
         }
     }
+
+    private final class BatteryListener extends IBatteryPropertiesListener.Stub {
+        public void batteryPropertiesChanged(BatteryProperties props) {
+            BatteryService.this.update(props);
+       }
+    }
 }
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index 957c448..3946f15 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -4,7 +4,6 @@
 LOCAL_SRC_FILES:= \
     com_android_server_AlarmManagerService.cpp \
     com_android_server_AssetAtlasService.cpp \
-    com_android_server_BatteryService.cpp \
     com_android_server_input_InputApplicationHandle.cpp \
     com_android_server_input_InputManagerService.cpp \
     com_android_server_input_InputWindowHandle.cpp \
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
deleted file mode 100644
index 0c8b4a5..0000000
--- a/services/jni/com_android_server_BatteryService.cpp
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "BatteryService"
-
-#include "JNIHelp.h"
-#include "jni.h"
-#include <utils/Log.h>
-#include <utils/misc.h>
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <linux/ioctl.h>
-#include <utils/Vector.h>
-#include <utils/String8.h>
-
-namespace android {
-
-#define POWER_SUPPLY_PATH "/sys/class/power_supply"
-
-struct FieldIds {
-    // members
-    jfieldID mAcOnline;
-    jfieldID mUsbOnline;
-    jfieldID mWirelessOnline;
-    jfieldID mBatteryStatus;
-    jfieldID mBatteryHealth;
-    jfieldID mBatteryPresent;
-    jfieldID mBatteryLevel;
-    jfieldID mBatteryVoltage;
-    jfieldID mBatteryTemperature;
-    jfieldID mBatteryTechnology;
-};
-static FieldIds gFieldIds;
-
-struct BatteryManagerConstants {
-    jint statusUnknown;
-    jint statusCharging;
-    jint statusDischarging;
-    jint statusNotCharging;
-    jint statusFull;
-    jint healthUnknown;
-    jint healthGood;
-    jint healthOverheat;
-    jint healthDead;
-    jint healthOverVoltage;
-    jint healthUnspecifiedFailure;
-    jint healthCold;
-};
-static BatteryManagerConstants gConstants;
-
-struct PowerSupplyPaths {
-    String8 batteryStatusPath;
-    String8 batteryHealthPath;
-    String8 batteryPresentPath;
-    String8 batteryCapacityPath;
-    String8 batteryVoltagePath;
-    String8 batteryTemperaturePath;
-    String8 batteryTechnologyPath;
-};
-static PowerSupplyPaths gPaths;
-
-static Vector<String8> gChargerNames;
-
-static int gVoltageDivisor = 1;
-
-enum PowerSupplyType {
-     ANDROID_POWER_SUPPLY_TYPE_UNKNOWN = 0,
-     ANDROID_POWER_SUPPLY_TYPE_AC,
-     ANDROID_POWER_SUPPLY_TYPE_USB,
-     ANDROID_POWER_SUPPLY_TYPE_WIRELESS,
-     ANDROID_POWER_SUPPLY_TYPE_BATTERY
-};
-
-static jint getBatteryStatus(const char* status)
-{
-    switch (status[0]) {
-        case 'C': return gConstants.statusCharging;         // Charging
-        case 'D': return gConstants.statusDischarging;      // Discharging
-        case 'F': return gConstants.statusFull;             // Full
-        case 'N': return gConstants.statusNotCharging;      // Not charging
-        case 'U': return gConstants.statusUnknown;          // Unknown
-            
-        default: {
-            ALOGW("Unknown battery status '%s'", status);
-            return gConstants.statusUnknown;
-        }
-    }
-}
-
-static jint getBatteryHealth(const char* status)
-{
-    switch (status[0]) {
-        case 'C': return gConstants.healthCold;         // Cold
-        case 'D': return gConstants.healthDead;         // Dead
-        case 'G': return gConstants.healthGood;         // Good
-        case 'O': {
-            if (strcmp(status, "Overheat") == 0) {
-                return gConstants.healthOverheat;
-            } else if (strcmp(status, "Over voltage") == 0) {
-                return gConstants.healthOverVoltage;
-            }
-            ALOGW("Unknown battery health[1] '%s'", status);
-            return gConstants.healthUnknown;
-        }
-        
-        case 'U': {
-            if (strcmp(status, "Unspecified failure") == 0) {
-                return gConstants.healthUnspecifiedFailure;
-            } else if (strcmp(status, "Unknown") == 0) {
-                return gConstants.healthUnknown;
-            }
-            // fall through
-        }
-            
-        default: {
-            ALOGW("Unknown battery health[2] '%s'", status);
-            return gConstants.healthUnknown;
-        }
-    }
-}
-
-static int readFromFile(const String8& path, char* buf, size_t size)
-{
-    if (path.isEmpty())
-        return -1;
-    int fd = open(path.string(), O_RDONLY, 0);
-    if (fd == -1) {
-        ALOGE("Could not open '%s'", path.string());
-        return -1;
-    }
-    
-    ssize_t count = read(fd, buf, size);
-    if (count > 0) {
-        while (count > 0 && buf[count-1] == '\n')
-            count--;
-        buf[count] = '\0';
-    } else {
-        buf[0] = '\0';
-    } 
-
-    close(fd);
-    return count;
-}
-
-static void setBooleanField(JNIEnv* env, jobject obj, const String8& path, jfieldID fieldID)
-{
-    const int SIZE = 16;
-    char buf[SIZE];
-    
-    jboolean value = false;
-    if (readFromFile(path, buf, SIZE) > 0) {
-        if (buf[0] != '0') {
-            value = true;
-        }
-    }
-    env->SetBooleanField(obj, fieldID, value);
-}
-
-static void setIntField(JNIEnv* env, jobject obj, const String8& path, jfieldID fieldID)
-{
-    const int SIZE = 128;
-    char buf[SIZE];
-    
-    jint value = 0;
-    if (readFromFile(path, buf, SIZE) > 0) {
-        value = atoi(buf);
-    }
-    env->SetIntField(obj, fieldID, value);
-}
-
-static void setVoltageField(JNIEnv* env, jobject obj, const String8& 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 PowerSupplyType readPowerSupplyType(const String8& path) {
-    const int SIZE = 128;
-    char buf[SIZE];
-    int length = readFromFile(path, buf, SIZE);
-
-    if (length <= 0)
-        return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
-    if (buf[length - 1] == '\n')
-        buf[length - 1] = 0;
-    if (strcmp(buf, "Battery") == 0)
-        return ANDROID_POWER_SUPPLY_TYPE_BATTERY;
-    else if (strcmp(buf, "Mains") == 0 || strcmp(buf, "USB_DCP") == 0 ||
-             strcmp(buf, "USB_CDP") == 0 || strcmp(buf, "USB_ACA") == 0)
-        return ANDROID_POWER_SUPPLY_TYPE_AC;
-    else if (strcmp(buf, "USB") == 0)
-        return ANDROID_POWER_SUPPLY_TYPE_USB;
-    else if (strcmp(buf, "Wireless") == 0)
-        return ANDROID_POWER_SUPPLY_TYPE_WIRELESS;
-    else
-        return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
-}
-
-static void android_server_BatteryService_update(JNIEnv* env, jobject obj)
-{
-    setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent);
-    
-    setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);
-    setVoltageField(env, obj, gPaths.batteryVoltagePath, gFieldIds.mBatteryVoltage);
-    setIntField(env, obj, gPaths.batteryTemperaturePath, gFieldIds.mBatteryTemperature);
-    
-    const int SIZE = 128;
-    char buf[SIZE];
-    
-    if (readFromFile(gPaths.batteryStatusPath, buf, SIZE) > 0)
-        env->SetIntField(obj, gFieldIds.mBatteryStatus, getBatteryStatus(buf));
-    else
-        env->SetIntField(obj, gFieldIds.mBatteryStatus,
-                         gConstants.statusUnknown);
-    
-    if (readFromFile(gPaths.batteryHealthPath, buf, SIZE) > 0)
-        env->SetIntField(obj, gFieldIds.mBatteryHealth, getBatteryHealth(buf));
-
-    if (readFromFile(gPaths.batteryTechnologyPath, buf, SIZE) > 0)
-        env->SetObjectField(obj, gFieldIds.mBatteryTechnology, env->NewStringUTF(buf));
-
-    unsigned int i;
-    String8 path;
-    jboolean acOnline = false;
-    jboolean usbOnline = false;
-    jboolean wirelessOnline = false;
-
-    for (i = 0; i < gChargerNames.size(); i++) {
-        path.clear();
-        path.appendFormat("%s/%s/online", POWER_SUPPLY_PATH,
-                          gChargerNames[i].string());
-
-        if (readFromFile(path, buf, SIZE) > 0) {
-            if (buf[0] != '0') {
-                path.clear();
-                path.appendFormat("%s/%s/type", POWER_SUPPLY_PATH,
-                                  gChargerNames[i].string());
-                switch(readPowerSupplyType(path)) {
-                case ANDROID_POWER_SUPPLY_TYPE_AC:
-                    acOnline = true;
-                    break;
-                case ANDROID_POWER_SUPPLY_TYPE_USB:
-                    usbOnline = true;
-                    break;
-                case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
-                    wirelessOnline = true;
-                    break;
-                default:
-                    ALOGW("%s: Unknown power supply type",
-                          gChargerNames[i].string());
-                }
-            }
-        }
-    }
-
-    env->SetBooleanField(obj, gFieldIds.mAcOnline, acOnline);
-    env->SetBooleanField(obj, gFieldIds.mUsbOnline, usbOnline);
-    env->SetBooleanField(obj, gFieldIds.mWirelessOnline, wirelessOnline);
-}
-
-static JNINativeMethod sMethods[] = {
-     /* name, signature, funcPtr */
-        {"native_update", "()V", (void*)android_server_BatteryService_update},
-};
-
-int register_android_server_BatteryService(JNIEnv* env)
-{
-    String8 path;
-    struct dirent* entry;
-
-    DIR* dir = opendir(POWER_SUPPLY_PATH);
-    if (dir == NULL) {
-        ALOGE("Could not open %s\n", POWER_SUPPLY_PATH);
-    } 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
-            path.clear();
-            path.appendFormat("%s/%s/type", POWER_SUPPLY_PATH, name);
-            switch(readPowerSupplyType(path)) {
-            case ANDROID_POWER_SUPPLY_TYPE_AC:
-            case ANDROID_POWER_SUPPLY_TYPE_USB:
-            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
-                path.clear();
-                path.appendFormat("%s/%s/online", POWER_SUPPLY_PATH, name);
-                if (access(path.string(), R_OK) == 0)
-                    gChargerNames.add(String8(name));
-                break;
-
-            case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
-                path.clear();
-                path.appendFormat("%s/%s/status", POWER_SUPPLY_PATH, name);
-                if (access(path, R_OK) == 0)
-                    gPaths.batteryStatusPath = path;
-                path.clear();
-                path.appendFormat("%s/%s/health", POWER_SUPPLY_PATH, name);
-                if (access(path, R_OK) == 0)
-                    gPaths.batteryHealthPath = path;
-                path.clear();
-                path.appendFormat("%s/%s/present", POWER_SUPPLY_PATH, name);
-                if (access(path, R_OK) == 0)
-                    gPaths.batteryPresentPath = path;
-                path.clear();
-                path.appendFormat("%s/%s/capacity", POWER_SUPPLY_PATH, name);
-                if (access(path, R_OK) == 0)
-                    gPaths.batteryCapacityPath = path;
-
-                path.clear();
-                path.appendFormat("%s/%s/voltage_now", POWER_SUPPLY_PATH, name);
-                if (access(path, R_OK) == 0) {
-                    gPaths.batteryVoltagePath = path;
-                    // voltage_now is in microvolts, not millivolts
-                    gVoltageDivisor = 1000;
-                } else {
-                    path.clear();
-                    path.appendFormat("%s/%s/batt_vol", POWER_SUPPLY_PATH, name);
-                    if (access(path, R_OK) == 0)
-                            gPaths.batteryVoltagePath = path;
-                }
-
-                path.clear();
-                path.appendFormat("%s/%s/temp", POWER_SUPPLY_PATH, name);
-                if (access(path, R_OK) == 0) {
-                    gPaths.batteryTemperaturePath = path;
-                } else {
-                    path.clear();
-                    path.appendFormat("%s/%s/batt_temp", POWER_SUPPLY_PATH, name);
-                    if (access(path, R_OK) == 0)
-                            gPaths.batteryTemperaturePath = path;
-                }
-
-                path.clear();
-                path.appendFormat("%s/%s/technology", POWER_SUPPLY_PATH, name);
-                if (access(path, R_OK) == 0)
-                    gPaths.batteryTechnologyPath = path;
-                break;
-
-            case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
-                break;
-            }
-        }
-        closedir(dir);
-    }
-
-    if (!gChargerNames.size())
-        ALOGE("No charger supplies found");
-    if (gPaths.batteryStatusPath.isEmpty())
-        ALOGE("batteryStatusPath not found");
-    if (gPaths.batteryHealthPath.isEmpty())
-        ALOGE("batteryHealthPath not found");
-    if (gPaths.batteryPresentPath.isEmpty())
-        ALOGE("batteryPresentPath not found");
-    if (gPaths.batteryCapacityPath.isEmpty())
-        ALOGE("batteryCapacityPath not found");
-    if (gPaths.batteryVoltagePath.isEmpty())
-        ALOGE("batteryVoltagePath not found");
-    if (gPaths.batteryTemperaturePath.isEmpty())
-        ALOGE("batteryTemperaturePath not found");
-    if (gPaths.batteryTechnologyPath.isEmpty())
-        ALOGE("batteryTechnologyPath not found");
-
-    jclass clazz = env->FindClass("com/android/server/BatteryService");
-
-    if (clazz == NULL) {
-        ALOGE("Can't find com/android/server/BatteryService");
-        return -1;
-    }
-    
-    gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z");
-    gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z");
-    gFieldIds.mWirelessOnline = env->GetFieldID(clazz, "mWirelessOnline", "Z");
-    gFieldIds.mBatteryStatus = env->GetFieldID(clazz, "mBatteryStatus", "I");
-    gFieldIds.mBatteryHealth = env->GetFieldID(clazz, "mBatteryHealth", "I");
-    gFieldIds.mBatteryPresent = env->GetFieldID(clazz, "mBatteryPresent", "Z");
-    gFieldIds.mBatteryLevel = env->GetFieldID(clazz, "mBatteryLevel", "I");
-    gFieldIds.mBatteryTechnology = env->GetFieldID(clazz, "mBatteryTechnology", "Ljava/lang/String;");
-    gFieldIds.mBatteryVoltage = env->GetFieldID(clazz, "mBatteryVoltage", "I");
-    gFieldIds.mBatteryTemperature = env->GetFieldID(clazz, "mBatteryTemperature", "I");
-
-    LOG_FATAL_IF(gFieldIds.mAcOnline == NULL, "Unable to find BatteryService.AC_ONLINE_PATH");
-    LOG_FATAL_IF(gFieldIds.mUsbOnline == NULL, "Unable to find BatteryService.USB_ONLINE_PATH");
-    LOG_FATAL_IF(gFieldIds.mWirelessOnline == NULL, "Unable to find BatteryService.WIRELESS_ONLINE_PATH");
-    LOG_FATAL_IF(gFieldIds.mBatteryStatus == NULL, "Unable to find BatteryService.BATTERY_STATUS_PATH");
-    LOG_FATAL_IF(gFieldIds.mBatteryHealth == NULL, "Unable to find BatteryService.BATTERY_HEALTH_PATH");
-    LOG_FATAL_IF(gFieldIds.mBatteryPresent == NULL, "Unable to find BatteryService.BATTERY_PRESENT_PATH");
-    LOG_FATAL_IF(gFieldIds.mBatteryLevel == NULL, "Unable to find BatteryService.BATTERY_CAPACITY_PATH");
-    LOG_FATAL_IF(gFieldIds.mBatteryVoltage == NULL, "Unable to find BatteryService.BATTERY_VOLTAGE_PATH");
-    LOG_FATAL_IF(gFieldIds.mBatteryTemperature == NULL, "Unable to find BatteryService.BATTERY_TEMPERATURE_PATH");
-    LOG_FATAL_IF(gFieldIds.mBatteryTechnology == NULL, "Unable to find BatteryService.BATTERY_TECHNOLOGY_PATH");
-    
-    clazz = env->FindClass("android/os/BatteryManager");
-    
-    if (clazz == NULL) {
-        ALOGE("Can't find android/os/BatteryManager");
-        return -1;
-    }
-    
-    gConstants.statusUnknown = env->GetStaticIntField(clazz, 
-            env->GetStaticFieldID(clazz, "BATTERY_STATUS_UNKNOWN", "I"));
-            
-    gConstants.statusCharging = env->GetStaticIntField(clazz, 
-            env->GetStaticFieldID(clazz, "BATTERY_STATUS_CHARGING", "I"));
-            
-    gConstants.statusDischarging = env->GetStaticIntField(clazz, 
-            env->GetStaticFieldID(clazz, "BATTERY_STATUS_DISCHARGING", "I"));
-    
-    gConstants.statusNotCharging = env->GetStaticIntField(clazz, 
-            env->GetStaticFieldID(clazz, "BATTERY_STATUS_NOT_CHARGING", "I"));
-    
-    gConstants.statusFull = env->GetStaticIntField(clazz, 
-            env->GetStaticFieldID(clazz, "BATTERY_STATUS_FULL", "I"));
-
-    gConstants.healthUnknown = env->GetStaticIntField(clazz, 
-            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_UNKNOWN", "I"));
-
-    gConstants.healthGood = env->GetStaticIntField(clazz, 
-            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_GOOD", "I"));
-
-    gConstants.healthOverheat = env->GetStaticIntField(clazz, 
-            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_OVERHEAT", "I"));
-
-    gConstants.healthDead = env->GetStaticIntField(clazz, 
-            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_DEAD", "I"));
-
-    gConstants.healthOverVoltage = env->GetStaticIntField(clazz, 
-            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_OVER_VOLTAGE", "I"));
-            
-    gConstants.healthUnspecifiedFailure = env->GetStaticIntField(clazz, 
-            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_UNSPECIFIED_FAILURE", "I"));
-    
-    gConstants.healthCold = env->GetStaticIntField(clazz,
-            env->GetStaticFieldID(clazz, "BATTERY_HEALTH_COLD", "I"));
-
-    return jniRegisterNativeMethods(env, "com/android/server/BatteryService", sMethods, NELEM(sMethods));
-}
-
-} /* namespace android */
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index bb679aa..736ef24f 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -21,7 +21,6 @@
 
 namespace android {
 int register_android_server_AlarmManagerService(JNIEnv* env);
-int register_android_server_BatteryService(JNIEnv* env);
 int register_android_server_InputApplicationHandle(JNIEnv* env);
 int register_android_server_InputWindowHandle(JNIEnv* env);
 int register_android_server_InputManager(JNIEnv* env);
@@ -57,7 +56,6 @@
     register_android_server_InputManager(env);
     register_android_server_LightsService(env);
     register_android_server_AlarmManagerService(env);
-    register_android_server_BatteryService(env);
     register_android_server_UsbDeviceManager(env);
     register_android_server_UsbHostManager(env);
     register_android_server_VibratorService(env);