AI 143800: am: CL 143748 Fix issue #1743326 (More battery stats)
  Adds stats for:
  - Number of raw user events that have happened in the system.
  - Number of times user activity has been reported, dividied by UID and type of activity.
  - Duration of screen brightness levels in 4 buckets.
  - Per-UID tracking of who has turned on Wifi and how long we can attribute it being on because of them.
  Original author: hackbod
  Merged from: //branches/cupcake/...

Automated import of CL 143800
diff --git a/services/java/com/android/server/HardwareService.java b/services/java/com/android/server/HardwareService.java
index 42367ef..5bc9b5f 100755
--- a/services/java/com/android/server/HardwareService.java
+++ b/services/java/com/android/server/HardwareService.java
@@ -16,6 +16,9 @@
 
 package com.android.server;
 
+import com.android.internal.app.IBatteryStats;
+import com.android.server.am.BatteryStatsService;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -63,6 +66,8 @@
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         mWakeLock.setReferenceCounted(true);
 
+        mBatteryStats = BatteryStatsService.getService();
+        
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SCREEN_OFF);
         context.registerReceiver(mIntentReceiver, filter);
@@ -200,6 +205,14 @@
         setLightBrightness_UNCHECKED(LIGHT_ID_BACKLIGHT, brightness);
         setLightBrightness_UNCHECKED(LIGHT_ID_KEYBOARD, brightness);
         setLightBrightness_UNCHECKED(LIGHT_ID_BUTTONS, brightness);
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mBatteryStats.noteScreenBrightness(brightness);
+        } catch (RemoteException e) {
+            Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 
     void setLightOff_UNCHECKED(int light) {
@@ -388,9 +401,11 @@
     private static native void setLight_native(int ptr, int light, int color, int mode,
             int onMS, int offMS);
 
-    private Context mContext;
-    private PowerManager.WakeLock mWakeLock;
+    private final Context mContext;
+    private final PowerManager.WakeLock mWakeLock;
 
+    private final IBatteryStats mBatteryStats;
+    
     volatile VibrateThread mThread;
     volatile Death mDeath;
     volatile IBinder mToken;
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index bbca401..9c6e9dc 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -1301,6 +1301,8 @@
                         err = Power.setScreenState(true);
                         long identity = Binder.clearCallingIdentity();
                         try {
+                            mBatteryStats.noteScreenBrightness(
+                                    getPreferredBrightness());
                             mBatteryStats.noteScreenOn();
                         } catch (RemoteException e) {
                             Log.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);
@@ -1455,6 +1457,8 @@
                             break;
                     }
                 }
+                int brightness = preferredBrightness;
+                int steps = ANIM_STEPS;
                 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
                     // dim or turn off backlight, depending on if the screen is on
                     // the scale is because the brightness ramp isn't linear and this biases
@@ -1463,7 +1467,6 @@
                     float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);
                     if (ratio > 1.0f) ratio = 1.0f;
                     if ((newState & SCREEN_ON_BIT) == 0) {
-                        int steps;
                         if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
                             // was bright
                             steps = ANIM_STEPS;
@@ -1471,10 +1474,8 @@
                             // was dim
                             steps = (int)(ANIM_STEPS*ratio*scale);
                         }
-                        mScreenBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
-                                steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
+                        brightness = Power.BRIGHTNESS_OFF;
                     } else {
-                        int steps;
                         if ((oldState & SCREEN_ON_BIT) != 0) {
                             // was bright
                             steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
@@ -1490,13 +1491,19 @@
                             // will then count going dim as turning off.
                             mScreenOffTime = SystemClock.elapsedRealtime();
                         }
-                        mScreenBrightness.setTargetLocked(Power.BRIGHTNESS_DIM,
-                                steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
+                        brightness = Power.BRIGHTNESS_DIM;
                     }
-                } else {
-                    mScreenBrightness.setTargetLocked(preferredBrightness,
-                            ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
                 }
+                long identity = Binder.clearCallingIdentity();
+                try {
+                    mBatteryStats.noteScreenBrightness(brightness);
+                } catch (RemoteException e) {
+                    // Nothing interesting to do.
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+                mScreenBrightness.setTargetLocked(brightness,
+                        steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
                 startAnimation = true;
             } else {
                 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
@@ -1735,6 +1742,16 @@
                         mUserState |= SCREEN_BRIGHT;
                     }
 
+                    int uid = Binder.getCallingUid();
+                    long ident = Binder.clearCallingIdentity();
+                    try {
+                        mBatteryStats.noteUserActivity(uid, eventType);
+                    } catch (RemoteException e) {
+                        // Ignore
+                    } finally {
+                        Binder.restoreCallingIdentity(ident);
+                    }
+                    
                     reactivateWakeLocksLocked();
                     mWakeLockState = mLocks.gatherState();
                     setPowerState(mUserState | mWakeLockState, noChangeLights, true);
@@ -1951,6 +1968,15 @@
         synchronized (mLocks) {
             Log.d(TAG, "system ready!");
             mDoneBooting = true;
+            long identity = Binder.clearCallingIdentity();
+            try {
+                mBatteryStats.noteScreenBrightness(getPreferredBrightness());
+                mBatteryStats.noteScreenOn();
+            } catch (RemoteException e) {
+                // Nothing interesting to do.
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
             userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
             updateWakeLockLocked();
             mLocks.notifyAll();
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 8e1d053..54e77f0 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -47,6 +47,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
+import android.os.Process;
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.util.Log;
@@ -167,6 +168,11 @@
     private char[] mScanResultBuffer;
     private boolean mNeedReconfig;
 
+    /*
+     * Last UID that asked to enable WIFI.
+     */
+    private int mLastEnableUid = Process.myUid();
+    
     /**
      * Number of allowed radio frequency channels in various regulatory domains.
      * This list is sufficient for 802.11b/g networks (2.4GHz range).
@@ -239,7 +245,7 @@
                 },
                 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
 
-        setWifiEnabledBlocking(wifiEnabled, false);
+        setWifiEnabledBlocking(wifiEnabled, false, Process.myUid());
     }
 
     /**
@@ -455,7 +461,8 @@
 
         synchronized (mWifiHandler) {
             sWakeLock.acquire();
-            sendEnableMessage(enable, true);
+            mLastEnableUid = Binder.getCallingUid();
+            sendEnableMessage(enable, true, Binder.getCallingUid());
         }
 
         return true;
@@ -465,10 +472,11 @@
      * Enables/disables Wi-Fi synchronously.
      * @param enable {@code true} to turn Wi-Fi on, {@code false} to turn it off.
      * @param persist {@code true} if the setting should be persisted.
+     * @param uid The UID of the process making the request.
      * @return {@code true} if the operation succeeds (or if the existing state
      *         is the same as the requested state)
      */
-    private boolean setWifiEnabledBlocking(boolean enable, boolean persist) {
+    private boolean setWifiEnabledBlocking(boolean enable, boolean persist, int uid) {
         final int eventualWifiState = enable ? WIFI_STATE_ENABLED : WIFI_STATE_DISABLED;
 
         if (mWifiState == eventualWifiState) {
@@ -478,18 +486,18 @@
             return false;
         }
 
-        setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING);
+        setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid);
 
         if (enable) {
             if (!WifiNative.loadDriver()) {
                 Log.e(TAG, "Failed to load Wi-Fi driver.");
-                setWifiEnabledState(WIFI_STATE_UNKNOWN);
+                setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
                 return false;
             }
             if (!WifiNative.startSupplicant()) {
                 WifiNative.unloadDriver();
                 Log.e(TAG, "Failed to start supplicant daemon.");
-                setWifiEnabledState(WIFI_STATE_UNKNOWN);
+                setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
                 return false;
             }
             registerForBroadcasts();
@@ -503,7 +511,7 @@
             boolean failedToStopSupplicantOrUnloadDriver = false;
             if (!WifiNative.stopSupplicant()) {
                 Log.e(TAG, "Failed to stop supplicant daemon.");
-                setWifiEnabledState(WIFI_STATE_UNKNOWN);
+                setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
                 failedToStopSupplicantOrUnloadDriver = true;
             }
 
@@ -513,7 +521,7 @@
             if (!WifiNative.unloadDriver()) {
                 Log.e(TAG, "Failed to unload Wi-Fi driver.");
                 if (!failedToStopSupplicantOrUnloadDriver) {
-                    setWifiEnabledState(WIFI_STATE_UNKNOWN);
+                    setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
                     failedToStopSupplicantOrUnloadDriver = true;
                 }
             }
@@ -527,7 +535,7 @@
         if (persist) {
             persistWifiEnabled(enable);
         }
-        setWifiEnabledState(eventualWifiState);
+        setWifiEnabledState(eventualWifiState, uid);
 
         /*
          * Initialize the hidden networks state and the number of allowed
@@ -541,15 +549,15 @@
         return true;
     }
 
-    private void setWifiEnabledState(int wifiState) {
+    private void setWifiEnabledState(int wifiState, int uid) {
         final int previousWifiState = mWifiState;
 
         long ident = Binder.clearCallingIdentity();
         try {
             if (wifiState == WIFI_STATE_ENABLED) {
-                mBatteryStats.noteWifiOn();
+                mBatteryStats.noteWifiOn(uid);
             } else if (wifiState == WIFI_STATE_DISABLED) {
-                mBatteryStats.noteWifiOff();
+                mBatteryStats.noteWifiOff(uid);
             }
         } catch (RemoteException e) {
         } finally {
@@ -1571,10 +1579,10 @@
         }
     };
 
-    private void sendEnableMessage(boolean enable, boolean persist) {
+    private void sendEnableMessage(boolean enable, boolean persist, int uid) {
         Message msg = Message.obtain(mWifiHandler,
                                      (enable ? MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI),
-                                     (persist ? 1 : 0), 0);
+                                     (persist ? 1 : 0), uid);
         msg.sendToTarget();
     }
 
@@ -1602,7 +1610,7 @@
             if (wifiShouldBeEnabled) {
                 if (wifiShouldBeStarted) {
                     sWakeLock.acquire();
-                    sendEnableMessage(true, false);
+                    sendEnableMessage(true, false, mLastEnableUid);
                     sWakeLock.acquire();
                     sendStartMessage(strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY);
                 } else {
@@ -1626,7 +1634,7 @@
                 }
             } else {
                 sWakeLock.acquire();
-                sendEnableMessage(false, false);
+                sendEnableMessage(false, false, mLastEnableUid);
             }
         }
     }
@@ -1671,7 +1679,7 @@
             switch (msg.what) {
 
                 case MESSAGE_ENABLE_WIFI:
-                    setWifiEnabledBlocking(true, msg.arg1 == 1);
+                    setWifiEnabledBlocking(true, msg.arg1 == 1, msg.arg2);
                     sWakeLock.release();
                     break;
 
@@ -1684,7 +1692,7 @@
                 case MESSAGE_DISABLE_WIFI:
                     // a non-zero msg.arg1 value means the "enabled" setting
                     // should be persisted
-                    setWifiEnabledBlocking(false, msg.arg1 == 1);
+                    setWifiEnabledBlocking(false, msg.arg1 == 1, msg.arg2);
                     sWakeLock.release();
                     break;
 
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 2e16157..270d15f 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -5085,6 +5085,11 @@
                         } else {
                             eventType = LocalPowerManager.OTHER_EVENT;
                         }
+                        try {
+                            mBatteryStats.noteInputEvent();
+                        } catch (RemoteException e) {
+                            // Ignore
+                        }
                         mPowerManager.userActivity(curTime, false, eventType);
                         switch (ev.classType) {
                             case RawInputEvent.CLASS_KEYBOARD:
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 2192e06..9ad994c 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -129,6 +129,13 @@
         }
     }
     
+    public void noteScreenBrightness(int brightness) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteScreenBrightnessLocked(brightness);
+        }
+    }
+    
     public void noteScreenOff() {
         enforceCallingPermission();
         synchronized (mStats) {
@@ -136,6 +143,20 @@
         }
     }
 
+    public void noteInputEvent() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteInputEventLocked();
+        }
+    }
+    
+    public void noteUserActivity(int uid, int event) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteUserActivityLocked(uid, event);
+        }
+    }
+    
     public void notePhoneOn() {
         enforceCallingPermission();
         synchronized (mStats) {
@@ -164,17 +185,17 @@
         }
     }
     
-    public void noteWifiOn() {
+    public void noteWifiOn(int uid) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteWifiOnLocked();
+            mStats.noteWifiOnLocked(uid);
         }
     }
     
-    public void noteWifiOff() {
+    public void noteWifiOff(int uid) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteWifiOffLocked();
+            mStats.noteWifiOffLocked(uid);
         }
     }