auto import from //branches/cupcake_rel/...@140373
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 3a9a59f..73ff501 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -176,6 +176,9 @@
     private synchronized final void update() {
         native_update();
 
+        boolean logOutlier = false;
+        long dischargeDuration = 0;
+        
         mBatteryLevelCritical = mBatteryLevel <= CRITICAL_BATTERY_LEVEL;
         if (mAcOnline) {
             mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
@@ -199,13 +202,12 @@
                     // 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) {
-                        long duration = SystemClock.elapsedRealtime() - mDischargeStartTime;
-                        EventLog.writeEvent(LOG_BATTERY_DISCHARGE_STATUS, duration,
+                        dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
+                        logOutlier = true;
+                        EventLog.writeEvent(LOG_BATTERY_DISCHARGE_STATUS, dischargeDuration,
                                 mDischargeStartLevel, mBatteryLevel);
                         // make sure we see a discharge event before logging again
                         mDischargeStartTime = 0; 
-                        
-                        logOutlier(duration);
                     }
                 } else if (mPlugType == BATTERY_PLUGGED_NONE) {
                     // charging -> discharging or we just powered up
@@ -231,7 +233,8 @@
                     mPlugType == BATTERY_PLUGGED_NONE) {
                 // We want to make sure we log discharge cycle outliers
                 // if the battery is about to die.
-                logOutlier(SystemClock.elapsedRealtime() - mDischargeStartTime);
+                dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
+                logOutlier = true;
             }
             
             mLastBatteryStatus = mBatteryStatus;
@@ -244,6 +247,11 @@
             mLastBatteryLevelCritical = mBatteryLevelCritical;
             
             sendIntent();
+            
+            // This needs to be done after sendIntent() so that we get the lastest battery stats.
+            if (logOutlier && dischargeDuration != 0) {
+                logOutlier(dischargeDuration);
+            }
         }
     }
 
@@ -252,7 +260,7 @@
         Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
         try {
-            mBatteryStats.setOnBattery(mPlugType == BATTERY_PLUGGED_NONE);
+            mBatteryStats.setOnBattery(mPlugType == BATTERY_PLUGGED_NONE, mBatteryLevel);
         } catch (RemoteException e) {
             // Should never happen.
         }
diff --git a/services/java/com/android/server/HardwareService.java b/services/java/com/android/server/HardwareService.java
index 2131ffdd..7466a37 100755
--- a/services/java/com/android/server/HardwareService.java
+++ b/services/java/com/android/server/HardwareService.java
@@ -35,11 +35,23 @@
 public class HardwareService extends IHardwareService.Stub {
     private static final String TAG = "HardwareService";
 
+    static final int LIGHT_ID_BACKLIGHT = 0;
+    static final int LIGHT_ID_KEYBOARD = 1;
+    static final int LIGHT_ID_BUTTONS = 2;
+    static final int LIGHT_ID_BATTERY = 3;
+    static final int LIGHT_ID_NOTIFICATIONS = 4;
+    static final int LIGHT_ID_ATTENTION = 5;
+
+    static final int LIGHT_FLASH_NONE = 0;
+    static final int LIGHT_FLASH_TIMED = 1;
+
     HardwareService(Context context) {
         // Reset the hardware to a default state, in case this is a runtime
         // restart instead of a fresh boot.
         vibratorOff();
 
+        mNativePointer = init_native();
+
         mContext = context;
         PowerManager pm = (PowerManager)context.getSystemService(
                 Context.POWER_SERVICE);
@@ -51,9 +63,18 @@
         context.registerReceiver(mIntentReceiver, filter);
     }
 
+    protected void finalize() throws Throwable {
+        finalize_native(mNativePointer);
+        super.finalize();
+    }
+
     public void vibrate(long milliseconds) {
-        vibratePattern(new long[] { 0, milliseconds }, -1,
-                       new Binder());
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires VIBRATE permission");
+        }
+        doCancelVibrate();
+        vibratorOn(milliseconds);
     }
 
     private boolean isAll0(long[] pattern) {
@@ -164,38 +185,40 @@
         Hardware.enableCameraFlash(milliseconds);
     }
 
-    public void setScreenBacklight(int brightness) {
+    public void setBacklights(int brightness) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) 
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires HARDWARE_TEST permission");
         }
         // Don't let applications turn the screen all the way off
         brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
-        Hardware.setScreenBacklight(brightness);
+        setLightBrightness_UNCHECKED(LIGHT_ID_BACKLIGHT, brightness);
+        setLightBrightness_UNCHECKED(LIGHT_ID_KEYBOARD, brightness);
+        setLightBrightness_UNCHECKED(LIGHT_ID_BUTTONS, brightness);
     }
 
-    public void setKeyboardBacklight(boolean on) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) 
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires HARDWARE_TEST permission");
-        }
-        Hardware.setKeyboardBacklight(on);
+    void setLightOff_UNCHECKED(int light) {
+        setLight_native(mNativePointer, light, 0, LIGHT_FLASH_NONE, 0, 0);
     }
 
-    public void setButtonBacklight(boolean on) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) 
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires HARDWARE_TEST permission");
-        }
-        Hardware.setButtonBacklight(on);
+    void setLightBrightness_UNCHECKED(int light, int brightness) {
+        int b = brightness & 0x000000ff;
+        b = 0xff000000 | (b << 16) | (b << 8) | b;
+        setLight_native(mNativePointer, light, b, LIGHT_FLASH_NONE, 0, 0);
     }
 
-    public void setLedState(int colorARGB, int onMS, int offMS) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) 
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires HARDWARE_TEST permission");
-        }
-        Hardware.setLedState(colorARGB, onMS, offMS);
+    void setLightColor_UNCHECKED(int light, int color) {
+        setLight_native(mNativePointer, light, color, LIGHT_FLASH_NONE, 0, 0);
+    }
+
+    void setLightFlashing_UNCHECKED(int light, int color, int mode, int onMS, int offMS) {
+        setLight_native(mNativePointer, light, color, mode, onMS, offMS);
+    }
+
+    public void setAttentionLight(boolean on) {
+        // Not worthy of a permission.  We shouldn't have a flashlight permission.
+        setLight_native(mNativePointer, LIGHT_ID_ATTENTION, on ? 0xffffffff : 0,
+                LIGHT_FLASH_NONE, 0, 0);
     }
 
     private void doCancelVibrate() {
@@ -206,8 +229,8 @@
                     mThread.notify();
                 }
                 mThread = null;
-                vibratorOff();
             }
+            vibratorOff();
         }
     }
 
@@ -315,6 +338,12 @@
             }
         }
     };
+    
+    private static native int init_native();
+    private static native void finalize_native(int ptr);
+
+    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;
@@ -323,6 +352,8 @@
     volatile Death mDeath;
     volatile IBinder mToken;
 
+    private int mNativePointer;
+
     native static void vibratorOn(long milliseconds);
     native static void vibratorOff();
 }
diff --git a/services/java/com/android/server/HeadsetObserver.java b/services/java/com/android/server/HeadsetObserver.java
index 855734d..c9066be 100644
--- a/services/java/com/android/server/HeadsetObserver.java
+++ b/services/java/com/android/server/HeadsetObserver.java
@@ -98,12 +98,12 @@
             sendIntent(isUnplug);
 
             if (isUnplug) {
-                // It often takes >200ms to flush the audio pipeline after apps
-                // pause audio playback, but audio route changes are immediate,
-                // so delay the route change by 400ms.
+                // It can take hundreds of ms flush the audio pipeline after
+                // apps pause audio playback, but audio route changes are
+                // immediate, so delay the route change by 1000ms.
                 // This could be improved once the audio sub-system provides an
                 // interface to clear the audio pipeline.
-                mHandler.sendEmptyMessageDelayed(0, 400);
+                mHandler.sendEmptyMessageDelayed(0, 1000);
             } else {
                 updateAudioRoute();
             }
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 9948322..4198154 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -308,6 +308,9 @@
                 mScreenOn = true;
             } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                 mScreenOn = false;
+            } else if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
+                hideInputMethodMenu();
+                return;
             } else {
                 Log.w(TAG, "Unexpected intent " + intent);
             }
@@ -436,6 +439,7 @@
         IntentFilter screenOnOffFilt = new IntentFilter();
         screenOnOffFilt.addAction(Intent.ACTION_SCREEN_ON);
         screenOnOffFilt.addAction(Intent.ACTION_SCREEN_OFF);
+        screenOnOffFilt.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         mContext.registerReceiver(new ScreenOnOffReceiver(), screenOnOffFilt);
         
         buildInputMethodListLocked(mMethodList, mMethodMap);
@@ -585,6 +589,8 @@
                         + mCurClient.pid + " uid " + mCurClient.uid);
             }
             mCurClient = null;
+            
+            hideInputMethodMenuLocked();
         }
     }
     
@@ -820,6 +826,7 @@
             mCurToken = null;
         }
         
+        mCurId = null;
         clearCurMethodLocked();
         
         if (reportToClient && mCurClient != null) {
@@ -896,10 +903,12 @@
                 setInputMethodLocked(id);
             } catch (IllegalArgumentException e) {
                 Log.w(TAG, "Unknown input method from prefs: " + id, e);
+                mCurMethodId = null;
                 unbindCurrentMethodLocked(true);
             }
         } else {
             // There is no longer an input method set, so stop any current one.
+            mCurMethodId = null;
             unbindCurrentMethodLocked(true);
         }
     }
@@ -1436,18 +1445,22 @@
     }
     
     void hideInputMethodMenu() {
+        synchronized (mMethodMap) {
+            hideInputMethodMenuLocked();
+        }
+    }
+    
+    void hideInputMethodMenuLocked() {
         if (DEBUG) Log.v(TAG, "Hide switching menu");
 
-        synchronized (mMethodMap) {
-            if (mSwitchingDialog != null) {
-                mSwitchingDialog.dismiss();
-                mSwitchingDialog = null;
-            }
-            
-            mDialogBuilder = null;
-            mItems = null;
-            mIms = null;
+        if (mSwitchingDialog != null) {
+            mSwitchingDialog.dismiss();
+            mSwitchingDialog = null;
         }
+        
+        mDialogBuilder = null;
+        mItems = null;
+        mIms = null;
     }
     
     // ----------------------------------------------------------------------
@@ -1584,7 +1597,7 @@
             }
             p.println("  mInputMethodIcon=" + mInputMethodIcon);
             p.println("  mInputMethodData=" + mInputMethodData);
-            p.println("  mCurrentMethod=" + mCurMethodId);
+            p.println("  mCurMethodId=" + mCurMethodId);
             client = mCurClient;
             p.println("  mCurClient=" + client + " mCurSeq=" + mCurSeq);
             p.println("  mCurFocusedWindow=" + mCurFocusedWindow);
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index 63b486c..411cd6b 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -176,7 +176,7 @@
                 keycode, repeatCount,
                 device != null ? device.mMetaKeysState : 0,
                 device != null ? device.id : -1, scancode,
-                flags);
+                flags | KeyEvent.FLAG_FROM_SYSTEM);
     }
     
     Thread mThread = new Thread("InputDeviceReader") {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index e48e047..5abf249 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -86,6 +86,7 @@
 public class LocationManagerService extends ILocationManager.Stub
         implements INetworkLocationManager {
     private static final String TAG = "LocationManagerService";
+    private static final boolean LOCAL_LOGV = false;
 
     // Minimum time interval between last known location writes, in milliseconds.
     private static final long MIN_LAST_KNOWN_LOCATION_TIME = 60L * 1000L;
@@ -338,8 +339,8 @@
         }
 
         public void binderDied() {
-            if (Config.LOGD) {
-                Log.d(TAG, "Location listener died");
+            if (LOCAL_LOGV) {
+                Log.v(TAG, "Location listener died");
             }
             synchronized (mLocationListeners) {
                 removeUpdatesLocked(this);
@@ -486,9 +487,9 @@
 
                 String name = subdirs[i].getName();
 
-                if (Config.LOGD) {
-                    Log.d(TAG, "Found dir " + subdirs[i].getAbsolutePath());
-                    Log.d(TAG, "name = " + name);
+                if (LOCAL_LOGV) {
+                    Log.v(TAG, "Found dir " + subdirs[i].getAbsolutePath());
+                    Log.v(TAG, "name = " + name);
                 }
 
                 // Don't create a fake provider if a real provider exists
@@ -551,8 +552,8 @@
         mContext = context;
         mLocationHandler = new LocationWorkerHandler();
 
-        if (Config.LOGD) {
-            Log.d(TAG, "Constructed LocationManager Service");
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "Constructed LocationManager Service");
         }
 
         // Alarm manager, needs to be done before calling loadProviders() below
@@ -731,8 +732,8 @@
     }
 
     private List<String> _getAllProvidersLocked() {
-        if (Config.LOGD) {
-            Log.d(TAG, "getAllProviders");
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "getAllProviders");
         }
         List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
         ArrayList<String> out = new ArrayList<String>(providers.size());
@@ -751,14 +752,14 @@
         } catch (SecurityException se) {
             throw se;
         } catch (Exception e) {
-            Log.e(TAG, "getProviders gotString exception:", e);
+            Log.e(TAG, "getProviders got exception:", e);
             return null;
         }
     }
 
     private List<String> _getProvidersLocked(boolean enabledOnly) {
-        if (Config.LOGD) {
-            Log.d(TAG, "getProviders");
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "getProviders");
         }
         List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
         ArrayList<String> out = new ArrayList<String>();
@@ -990,8 +991,8 @@
 
     private void requestLocationUpdatesLocked(String provider,
             long minTime, float minDistance, Receiver receiver) {
-        if (Config.LOGD) {
-            Log.d(TAG, "_requestLocationUpdates: listener = " + receiver);
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "_requestLocationUpdates: listener = " + receiver);
         }
 
         LocationProviderImpl impl = LocationProviderImpl.getProvider(provider);
@@ -1088,8 +1089,8 @@
     }
 
     private void removeUpdatesLocked(Receiver receiver) {
-        if (Config.LOGD) {
-            Log.d(TAG, "_removeUpdates: listener = " + receiver);
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "_removeUpdates: listener = " + receiver);
         }
 
         // so wakelock calls will succeed
@@ -1292,8 +1293,8 @@
                     boolean inProximity =
                         alert.isInProximity(latitude, longitude);
                     if (!entered && inProximity) {
-                        if (Config.LOGD) {
-                            Log.i(TAG, "Entered alert");
+                        if (LOCAL_LOGV) {
+                            Log.v(TAG, "Entered alert");
                         }
                         mProximitiesEntered.add(alert);
                         Intent enteredIntent = new Intent();
@@ -1301,8 +1302,8 @@
                         try {
                             intent.send(mContext, 0, enteredIntent, null, null);
                         } catch (PendingIntent.CanceledException e) {
-                            if (Config.LOGD) {
-                                Log.i(TAG, "Canceled proximity alert: " + alert, e);
+                            if (LOCAL_LOGV) {
+                                Log.v(TAG, "Canceled proximity alert: " + alert, e);
                             }
                             if (intentsToRemove == null) {
                                 intentsToRemove = new ArrayList<PendingIntent>();
@@ -1310,8 +1311,8 @@
                             intentsToRemove.add(intent);
                         }
                     } else if (entered && !inProximity) {
-                        if (Config.LOGD) {
-                            Log.i(TAG, "Exited alert");
+                        if (LOCAL_LOGV) {
+                            Log.v(TAG, "Exited alert");
                         }
                         mProximitiesEntered.remove(alert);
                         Intent exitedIntent = new Intent();
@@ -1319,8 +1320,8 @@
                         try {
                             intent.send(mContext, 0, exitedIntent, null, null);
                         } catch (PendingIntent.CanceledException e) {
-                            if (Config.LOGD) {
-                                Log.i(TAG, "Canceled proximity alert: " + alert, e);
+                            if (LOCAL_LOGV) {
+                                Log.v(TAG, "Canceled proximity alert: " + alert, e);
                             }
                             if (intentsToRemove == null) {
                                 intentsToRemove = new ArrayList<PendingIntent>();
@@ -1330,8 +1331,8 @@
                     }
                 } else {
                     // Mark alert for expiration
-                    if (Config.LOGD) {
-                        Log.i(TAG, "Expiring proximity alert: " + alert);
+                    if (LOCAL_LOGV) {
+                        Log.v(TAG, "Expiring proximity alert: " + alert);
                     }
                     if (intentsToRemove == null) {
                         intentsToRemove = new ArrayList<PendingIntent>();
@@ -1387,8 +1388,8 @@
 
     private void addProximityAlertLocked(double latitude, double longitude,
         float radius, long expiration, PendingIntent intent) {
-        if (Config.LOGD) {
-            Log.d(TAG, "addProximityAlert: latitude = " + latitude +
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "addProximityAlert: latitude = " + latitude +
                     ", longitude = " + longitude +
                     ", expiration = " + expiration +
                     ", intent = " + intent);
@@ -1439,8 +1440,8 @@
     }
 
     private void removeProximityAlertLocked(PendingIntent intent) {
-        if (Config.LOGD) {
-            Log.d(TAG, "removeProximityAlert: intent = " + intent);
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "removeProximityAlert: intent = " + intent);
         }
 
         mProximityAlerts.remove(intent);
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index bc4b169..c4b0587 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -38,7 +38,6 @@
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.Handler;
-import android.os.Hardware;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.Power;
@@ -80,6 +79,7 @@
 
     private WorkerHandler mHandler;
     private StatusBarService mStatusBarService;
+    private HardwareService mHardware;
 
     private NotificationRecord mSoundNotification;
     private AsyncPlayer mSound;
@@ -99,25 +99,11 @@
     private boolean mBatteryFull;
     private NotificationRecord mLedNotification;
     
-    // Low battery - red, blinking on 0.125s every 3 seconds
-    private static final int BATTERY_LOW_ARGB = 0xFFFF0000;
-    private static final int BATTERY_LOW_ON = 125;
-    private static final int BATTERY_LOW_OFF = 2875;
-
-    // Charging Low - red solid on
-    private static final int CHARGING_LOW_ARGB = 0xFFFF0000;
-    private static final int CHARGING_LOW_ON = 0;
-    private static final int CHARGING_LOW_OFF = 0;
-
-    // Charging - orange solid on
-    private static final int CHARGING_ARGB = 0xFFFFFF00;
-    private static final int CHARGING_ON = 0;
-    private static final int CHARGING_OFF = 0;
-
-    // Charging Full - green solid on
-    private static final int CHARGING_FULL_ARGB = 0xFF00FF00;
-    private static final int CHARGING_FULL_ON = 0;
-    private static final int CHARGING_FULL_OFF = 0;
+    private static final int BATTERY_LOW_ARGB = 0xFFFF0000; // Charging Low - red solid on
+    private static final int BATTERY_MEDIUM_ARGB = 0xFFFFFF00;    // Charging - orange solid on
+    private static final int BATTERY_FULL_ARGB = 0xFF00FF00; // Charging Full - green solid on
+    private static final int BATTERY_BLINK_ON = 125;
+    private static final int BATTERY_BLINK_OFF = 2875;
 
     // Tag IDs for EventLog.
     private static final int EVENT_LOG_ENQUEUE = 2750;
@@ -326,10 +312,12 @@
         }
     };
 
-    NotificationManagerService(Context context, StatusBarService statusBar)
+    NotificationManagerService(Context context, StatusBarService statusBar,
+            HardwareService hardware)
     {
         super();
         mContext = context;
+        mHardware = hardware;
         mAm = ActivityManagerNative.getDefault();
         mSound = new AsyncPlayer(TAG);
         mSound.setUsesWakeLock(context);
@@ -830,35 +818,40 @@
     // lock on mNotificationList
     private void updateLightsLocked()
     {
-        // battery low has highest priority, then charging
-        if (mBatteryLow && !mBatteryCharging) {
-            Hardware.setLedState(BATTERY_LOW_ARGB, BATTERY_LOW_ON, BATTERY_LOW_OFF);
+        // Battery low always shows, other states only show if charging.
+        if (mBatteryLow) {
+            mHardware.setLightFlashing_UNCHECKED(HardwareService.LIGHT_ID_BATTERY, BATTERY_LOW_ARGB,
+                    HardwareService.LIGHT_FLASH_TIMED, BATTERY_BLINK_ON, BATTERY_BLINK_OFF);
         } else if (mBatteryCharging) {
-            if (mBatteryLow) {
-                Hardware.setLedState(CHARGING_LOW_ARGB, CHARGING_LOW_ON, CHARGING_LOW_OFF);
-            } else if (mBatteryFull) {
-                Hardware.setLedState(CHARGING_FULL_ARGB, CHARGING_FULL_ON, CHARGING_FULL_OFF);
+            if (mBatteryFull) {
+                mHardware.setLightColor_UNCHECKED(HardwareService.LIGHT_ID_BATTERY,
+                        BATTERY_FULL_ARGB);
             } else {
-                Hardware.setLedState(CHARGING_ARGB, CHARGING_ON, CHARGING_OFF);
+                mHardware.setLightColor_UNCHECKED(HardwareService.LIGHT_ID_BATTERY,
+                        BATTERY_MEDIUM_ARGB);
             }
         } else {
-            // handle notification lights
-            if (mLedNotification == null) {
-                // get next notification, if any
-                int n = mLights.size();
-                if (n > 0) {
-                    mLedNotification = mLights.get(n-1);
-                }
-            }
+            mHardware.setLightOff_UNCHECKED(HardwareService.LIGHT_ID_BATTERY);
+        }
 
-            if (mLedNotification == null) {
-                Hardware.setLedState(0, 0, 0);
-            } else {
-                Hardware.setLedState(mLedNotification.notification.ledARGB,
-                        mLedNotification.notification.ledOnMS,
-                        mLedNotification.notification.ledOffMS);
+        // handle notification lights
+        if (mLedNotification == null) {
+            // get next notification, if any
+            int n = mLights.size();
+            if (n > 0) {
+                mLedNotification = mLights.get(n-1);
             }
         }
+        if (mLedNotification == null) {
+            mHardware.setLightOff_UNCHECKED(HardwareService.LIGHT_ID_NOTIFICATIONS);
+        } else {
+            mHardware.setLightFlashing_UNCHECKED(
+                    HardwareService.LIGHT_ID_NOTIFICATIONS,
+                    mLedNotification.notification.ledARGB,
+                    HardwareService.LIGHT_FLASH_TIMED,
+                    mLedNotification.notification.ledOnMS,
+                    mLedNotification.notification.ledOffMS);
+        }
     }
 
     // lock on mNotificationList
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 9f428e9..2cf47df 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -57,7 +57,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.Signature;
-import android.content.pm.PackageParser.Package;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -129,6 +128,7 @@
     static final int SCAN_FORCE_DEX = 1<<2;
     static final int SCAN_UPDATE_SIGNATURE = 1<<3;
     static final int SCAN_FORWARD_LOCKED = 1<<4;
+    static final int SCAN_NEW_INSTALL = 1<<5;
     
     static final int LOG_BOOT_PROGRESS_PMS_START = 3060;
     static final int LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START = 3070;
@@ -1963,6 +1963,31 @@
                 }
                 removeExisting = true;
             }
+            
+            // Verify that this new package doesn't have any content providers
+            // that conflict with existing packages.  Only do this if the
+            // package isn't already installed, since we don't want to break
+            // things that are installed.
+            if ((scanMode&SCAN_NEW_INSTALL) != 0) {
+                int N = pkg.providers.size();
+                int i;
+                for (i=0; i<N; i++) {
+                    PackageParser.Provider p = pkg.providers.get(i);
+                    String names[] = p.info.authority.split(";");
+                    for (int j = 0; j < names.length; j++) {
+                        if (mProviders.containsKey(names[j])) {
+                            PackageParser.Provider other = mProviders.get(names[j]);
+                            Log.w(TAG, "Can't install because provider name " + names[j] +
+                                    " (in package " + pkg.applicationInfo.packageName +
+                                    ") is already used by "
+                                    + ((other != null && other.component != null)
+                                            ? other.component.getPackageName() : "?"));
+                            mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
+                            return null;
+                        }
+                    }
+                }
+            }
         }
 
         if (removeExisting) {
@@ -2181,9 +2206,12 @@
                             ", className = " + p.info.name +
                             ", isSyncable = " + p.info.isSyncable);
                     } else {
+                        PackageParser.Provider other = mProviders.get(names[j]);
                         Log.w(TAG, "Skipping provider name " + names[j] +
                               " (in package " + pkg.applicationInfo.packageName +
-                              "): name already used");
+                              "): name already used by "
+                              + ((other != null && other.component != null)
+                                      ? other.component.getPackageName() : "?"));
                     }
                 }
                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
@@ -3205,7 +3233,7 @@
                 mHandler.removeCallbacks(this);
                 PackageInstalledInfo res;
                 synchronized (mInstallLock) {
-                    res = installPackageLI(packageURI, flags);
+                    res = installPackageLI(packageURI, flags, true);
                 }
                 if (observer != null) {
                     try {
@@ -3246,7 +3274,7 @@
     private void installNewPackageLI(String pkgName,
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
-            PackageParser.Package pkg, boolean forwardLocked,
+            PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
             PackageInstalledInfo res) {
         // Remember this for later, in case we need to rollback this install
         boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
@@ -3270,7 +3298,8 @@
                 destResourceFile, pkg, 0,
                 SCAN_MONITOR | SCAN_FORCE_DEX
                 | SCAN_UPDATE_SIGNATURE 
-                | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
+                | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
+                | (newInstall ? SCAN_NEW_INSTALL : 0));
         if (newPackage == null) {
             Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -3302,7 +3331,7 @@
     private void replacePackageLI(String pkgName,
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
-            PackageParser.Package pkg, boolean forwardLocked,
+            PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
             PackageInstalledInfo res) {
         PackageParser.Package deletedPackage;
         // First find the old package info and check signatures
@@ -3317,17 +3346,19 @@
         if(sysPkg) {
             replaceSystemPackageLI(deletedPackage, 
                     tmpPackageFile, destFilePath, 
-                    destPackageFile, destResourceFile, pkg, forwardLocked, res);
+                    destPackageFile, destResourceFile, pkg, forwardLocked,
+                    newInstall, res);
         } else {
             replaceNonSystemPackageLI(deletedPackage, tmpPackageFile, destFilePath, 
-                    destPackageFile, destResourceFile, pkg, forwardLocked, res);
+                    destPackageFile, destResourceFile, pkg, forwardLocked,
+                    newInstall, res);
         }
     }
     
     private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
-            PackageParser.Package pkg, boolean forwardLocked,
+            PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
             PackageInstalledInfo res) {
         PackageParser.Package newPackage = null;
         String pkgName = deletedPackage.packageName;
@@ -3347,7 +3378,8 @@
                     destResourceFile, pkg, parseFlags,
                     SCAN_MONITOR | SCAN_FORCE_DEX
                     | SCAN_UPDATE_SIGNATURE 
-                    | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
+                    | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
+                    | (newInstall ? SCAN_NEW_INSTALL : 0));
             if (newPackage == null) {
                     Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
                 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -3404,7 +3436,7 @@
                         Uri.fromFile(new File(deletedPackage.mPath)),
                         isForwardLocked(deletedPackage)
                         ? PackageManager.FORWARD_LOCK_PACKAGE
-                                : 0);
+                                : 0, false);
             }
         }
     }
@@ -3412,7 +3444,7 @@
     private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
-            PackageParser.Package pkg, boolean forwardLocked,
+            PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
             PackageInstalledInfo res) {
         PackageParser.Package newPackage = null;
         boolean updatedSettings = false;
@@ -3450,7 +3482,8 @@
                 destResourceFile, pkg, parseFlags,
                 SCAN_MONITOR | SCAN_FORCE_DEX
                 | SCAN_UPDATE_SIGNATURE 
-                | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
+                | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
+                | (newInstall ? SCAN_NEW_INSTALL : 0));
         if (newPackage == null) {
             Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -3484,8 +3517,7 @@
                     oldPkgSetting.resourcePath,
                     oldPkg, parseFlags,
                     SCAN_MONITOR
-                    | SCAN_UPDATE_SIGNATURE
-                    | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
+                    | SCAN_UPDATE_SIGNATURE);
             // Restore the old system information in Settings
             synchronized(mPackages) {
                 if(updatedSettings) {
@@ -3556,7 +3588,8 @@
         }
     }
     
-    private PackageInstalledInfo installPackageLI(Uri pPackageURI, int pFlags) {
+    private PackageInstalledInfo installPackageLI(Uri pPackageURI,
+            int pFlags, boolean newInstall) {
         File tmpPackageFile = null;
         String pkgName = null;
         boolean forwardLocked = false;
@@ -3669,21 +3702,21 @@
                 replacePackageLI(pkgName,
                         tmpPackageFile, 
                         destFilePath, destPackageFile, destResourceFile,
-                        pkg, forwardLocked,
+                        pkg, forwardLocked, newInstall,
                         res);
             } else {
                 installNewPackageLI(pkgName,
                         tmpPackageFile, 
                         destFilePath, destPackageFile, destResourceFile,
-                        pkg, forwardLocked,
+                        pkg, forwardLocked, newInstall,
                         res);
             }
         } finally {
             if (tmpPackageFile != null && tmpPackageFile.exists()) {
                 tmpPackageFile.delete();
             }
-            return res;
         }
+        return res;
     }
     
     private int setPermissionsLI(String pkgName,
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index ad30ffc..5c7ab93 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -154,6 +154,7 @@
     private final LockList mLocks = new LockList();
     private Intent mScreenOffIntent;
     private Intent mScreenOnIntent;
+    private HardwareService mHardware;
     private Context mContext;
     private UnsynchronizedWakeLock mBroadcastWakeLock;
     private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock;
@@ -164,11 +165,11 @@
     private TimeoutTask mTimeoutTask = new TimeoutTask();
     private LightAnimator mLightAnimator = new LightAnimator();
     private final BrightnessState mScreenBrightness
-            = new BrightnessState(Power.SCREEN_LIGHT);
+            = new BrightnessState(SCREEN_BRIGHT_BIT);
     private final BrightnessState mKeyboardBrightness
-            = new BrightnessState(Power.KEYBOARD_LIGHT);
+            = new BrightnessState(KEYBOARD_BRIGHT_BIT);
     private final BrightnessState mButtonBrightness
-            = new BrightnessState(Power.BUTTON_LIGHT);
+            = new BrightnessState(BUTTON_BRIGHT_BIT);
     private boolean mIsPowered = false;
     private IActivityManager mActivityService;
     private IBatteryStats mBatteryStats;
@@ -357,7 +358,9 @@
 
     private ContentQueryMap mSettings;
 
-    void init(Context context, IActivityManager activity, BatteryService battery) {
+    void init(Context context, HardwareService hardware, IActivityManager activity,
+            BatteryService battery) {
+        mHardware = hardware;
         mContext = context;
         mActivityService = activity;
         mBatteryStats = BatteryStatsService.getService();
@@ -1226,10 +1229,7 @@
             }
 
             if (mPowerState != newState) {
-                err = updateLightsLocked(newState, 0);
-                if (err != 0) {
-                    return;
-                }
+                updateLightsLocked(newState, 0);
                 mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
             }
 
@@ -1327,11 +1327,11 @@
                 mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
     }
 
-    private int updateLightsLocked(int newState, int forceState) {
+    private void updateLightsLocked(int newState, int forceState) {
         int oldState = mPowerState;
         int difference = (newState ^ oldState) | forceState;
         if (difference == 0) {
-            return 0;
+            return;
         }
         
         int offMask = 0;
@@ -1353,9 +1353,9 @@
                 startAnimation = true;
             } else {
                 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
-                    offMask |= Power.KEYBOARD_LIGHT;
+                    offMask |= KEYBOARD_BRIGHT_BIT;
                 } else {
-                    onMask |= Power.KEYBOARD_LIGHT;
+                    onMask |= KEYBOARD_BRIGHT_BIT;
                 }
             }
         }
@@ -1372,9 +1372,9 @@
                 startAnimation = true;
             } else {
                 if ((newState & BUTTON_BRIGHT_BIT) == 0) {
-                    offMask |= Power.BUTTON_LIGHT;
+                    offMask |= BUTTON_BRIGHT_BIT;
                 } else {
-                    onMask |= Power.BUTTON_LIGHT;
+                    onMask |= BUTTON_BRIGHT_BIT;
                 }
             }
         }
@@ -1428,12 +1428,12 @@
                 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
                     // dim or turn off backlight, depending on if the screen is on
                     if ((newState & SCREEN_ON_BIT) == 0) {
-                        offMask |= Power.SCREEN_LIGHT;
+                        offMask |= SCREEN_BRIGHT_BIT;
                     } else {
-                        dimMask |= Power.SCREEN_LIGHT;
+                        dimMask |= SCREEN_BRIGHT_BIT;
                     }
                 } else {
-                    onMask |= Power.SCREEN_LIGHT;
+                    onMask |= SCREEN_BRIGHT_BIT;
                 }
             }
         }
@@ -1446,10 +1446,9 @@
             mHandler.post(mLightAnimator);
         }
         
-        int err = 0;
         if (offMask != 0) {
             //Log.i(TAG, "Setting brightess off: " + offMask);
-            err |= Power.setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
+            setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
         }
         if (dimMask != 0) {
             int brightness = Power.BRIGHTNESS_DIM;
@@ -1458,7 +1457,7 @@
                 brightness = Power.BRIGHTNESS_LOW_BATTERY;
             }
             //Log.i(TAG, "Setting brightess dim " + brightness + ": " + offMask);
-            err |= Power.setLightBrightness(dimMask, brightness);
+            setLightBrightness(dimMask, brightness);
         }
         if (onMask != 0) {
             int brightness = getPreferredBrightness();
@@ -1467,10 +1466,20 @@
                 brightness = Power.BRIGHTNESS_LOW_BATTERY;
             }
             //Log.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
-            err |= Power.setLightBrightness(onMask, brightness);
+            setLightBrightness(onMask, brightness);
         }
+    }
 
-        return err;
+    private void setLightBrightness(int mask, int value) {
+        if ((mask & SCREEN_BRIGHT_BIT) != 0) {
+            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, value);
+        }
+        if ((mask & BUTTON_BRIGHT_BIT) != 0) {
+            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, value);
+        }
+        if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
+            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, value);
+        }
     }
 
     class BrightnessState {
@@ -1530,10 +1539,10 @@
                 }
             }
             //Log.i(TAG, "Animating brightess " + curIntValue + ": " + mask);
-            Power.setLightBrightness(mask, curIntValue);
+            setLightBrightness(mask, curIntValue);
             animating = more;
             if (!more) {
-                if (mask == Power.SCREEN_LIGHT && curIntValue == Power.BRIGHTNESS_OFF) {
+                if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
                     screenOffFinishedAnimating(mOffBecauseOfUser);
                 }
             }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a629ec6..1f508a6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -86,6 +86,7 @@
         int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
                 : Integer.parseInt(factoryTestStr);
 
+        HardwareService hardware = null;
         PowerManagerService power = null;
         IPackageManager pm = null;
         Context context = null;
@@ -127,9 +128,13 @@
             BatteryService battery = new BatteryService(context);
             ServiceManager.addService("battery", battery);
 
+            Log.i(TAG, "Starting Hardware Service.");
+            hardware = new HardwareService(context);
+            ServiceManager.addService("hardware", hardware);
+
             // only initialize the power service after we have started the
-            // content providers and the batter service.
-            power.init(context, ActivityManagerService.getDefault(), battery);
+            // hardware service, content providers and the battery service.
+            power.init(context, hardware, ActivityManagerService.getDefault(), battery);
 
             Log.i(TAG, "Starting Alarm Manager.");
             AlarmManagerService alarm = new AlarmManagerService(context);
@@ -171,7 +176,7 @@
                 int bluetoothOn = Settings.Secure.getInt(mContentResolver,
                     Settings.Secure.BLUETOOTH_ON, 0);
                 if (bluetoothOn > 0) {
-                    bluetooth.enable(null);
+                    bluetooth.enable();
                 }
             }
 
@@ -208,13 +213,6 @@
             }
 
             try {
-                Log.i(TAG, "Starting Hardware Service.");
-                ServiceManager.addService("hardware", new HardwareService(context));
-            } catch (Throwable e) {
-                Log.e(TAG, "Failure starting Hardware Service", e);
-            }
-
-            try {
                 Log.i(TAG, "Starting NetStat Service.");
                 ServiceManager.addService("netstat", new NetStatService(context));
             } catch (Throwable e) {
@@ -232,7 +230,7 @@
             try {
                 Log.i(TAG, "Starting Notification Manager.");
                 ServiceManager.addService(Context.NOTIFICATION_SERVICE,
-                        new NotificationManagerService(context, statusBar));
+                        new NotificationManagerService(context, statusBar, hardware));
             } catch (Throwable e) {
                 Log.e(TAG, "Failure starting Notification Manager", e);
             }
diff --git a/services/java/com/android/server/ViewServer.java b/services/java/com/android/server/ViewServer.java
index 4201b39..07826a6 100644
--- a/services/java/com/android/server/ViewServer.java
+++ b/services/java/com/android/server/ViewServer.java
@@ -24,6 +24,9 @@
 import java.io.IOException;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
 
 /**
  * The ViewServer is local socket server that can be used to communicate with the
@@ -41,7 +44,14 @@
     // Debug facility
     private static final String LOG_TAG = "ViewServer";
 
+    private static final String VALUE_PROTOCOL_VERSION = "2";
+    private static final String VALUE_SERVER_VERSION = "2";
+
     // Protocol commands
+    // Returns the protocol version
+    private static final String COMMAND_PROTOCOL_VERSION = "PROTOCOL";
+    // Returns the server version
+    private static final String COMMAND_SERVER_VERSION = "SERVER";
     // Lists all of the available windows in the system
     private static final String COMMAND_WINDOW_MANAGER_LIST = "LIST";
 
@@ -169,7 +179,11 @@
                     }
 
                     boolean result;
-                    if (COMMAND_WINDOW_MANAGER_LIST.equalsIgnoreCase(command)) {
+                    if (COMMAND_PROTOCOL_VERSION.equalsIgnoreCase(command)) {
+                        result = writeValue(client, VALUE_PROTOCOL_VERSION);
+                    } else if (COMMAND_SERVER_VERSION.equalsIgnoreCase(command)) {
+                        result = writeValue(client, VALUE_SERVER_VERSION);
+                    } else if (COMMAND_WINDOW_MANAGER_LIST.equalsIgnoreCase(command)) {
                         result = mWindowManager.viewServerListWindows(client);
                     } else {
                         result = mWindowManager.viewServerWindowCommand(client,
@@ -197,4 +211,28 @@
             }
         }
     }
+
+    private static boolean writeValue(Socket client, String value) {
+        boolean result;
+        BufferedWriter out = null;
+        try {
+            OutputStream clientStream = client.getOutputStream();
+            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
+            out.write(value);
+            out.write("\n");
+            out.flush();
+            result = true;
+        } catch (Exception e) {
+            result = false;
+        } finally {
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException e) {
+                    result = false;
+                }
+            }
+        }
+        return result;
+    }
 }
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index e298f49..ddf92e2 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -50,6 +50,7 @@
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.util.Log;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
 import java.util.ArrayList;
@@ -62,6 +63,10 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.os.BatteryStatsImpl;
+import com.android.server.am.BatteryStatsService;
+
 /**
  * WifiService handles remote WiFi operation requests by implementing
  * the IWifiManager interface. It also creates a WifiMonitor to listen
@@ -86,6 +91,9 @@
     private int mPluggedType;
 
     private final LockList mLocks = new LockList();
+
+    private final IBatteryStats mBatteryStats;
+    
     /**
      * See {@link Settings.Gservices#WIFI_IDLE_MS}. This is the default value if a
      * Settings.Gservices value is not present. This timeout value is chosen as
@@ -168,7 +176,8 @@
     WifiService(Context context, WifiStateTracker tracker) {
         mContext = context;
         mWifiStateTracker = tracker;
-
+        mBatteryStats = BatteryStatsService.getService();
+        
         /*
          * Initialize the hidden-networks state
          */
@@ -532,6 +541,18 @@
     private void setWifiEnabledState(int wifiState) {
         final int previousWifiState = mWifiState;
 
+        long ident = Binder.clearCallingIdentity();
+        try {
+            if (wifiState == WIFI_STATE_ENABLED) {
+                mBatteryStats.noteWifiOn();
+            } else if (wifiState == WIFI_STATE_DISABLED) {
+                mBatteryStats.noteWifiOff();
+            }
+        } catch (RemoteException e) {
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        
         // Update state
         mWifiState = wifiState;
 
@@ -1828,6 +1849,19 @@
 
     private boolean acquireWifiLockLocked(WifiLock wifiLock) {
         mLocks.addLock(wifiLock);
+        
+        int uid = Binder.getCallingUid();
+        long ident = Binder.clearCallingIdentity();
+        try {
+            switch(wifiLock.mLockMode) {
+            case (WifiManager.WIFI_MODE_FULL): mBatteryStats.noteFullWifiLockAcquired(uid);
+            case (WifiManager.WIFI_MODE_SCAN_ONLY): mBatteryStats.noteScanWifiLockAcquired(uid);
+            }
+        } catch (RemoteException e) {
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        
         updateWifiState();
         return true;
     }
@@ -1841,7 +1875,22 @@
 
     private boolean releaseWifiLockLocked(IBinder lock) {
         boolean result;
-        result = (mLocks.removeLock(lock) != null);
+        
+        WifiLock wifiLock = mLocks.removeLock(lock);
+        result = (wifiLock != null);
+        
+        int uid = Binder.getCallingUid();
+        long ident = Binder.clearCallingIdentity();
+        try {
+            switch(wifiLock.mLockMode) {
+            case (WifiManager.WIFI_MODE_FULL): mBatteryStats.noteFullWifiLockReleased(uid);
+            case (WifiManager.WIFI_MODE_SCAN_ONLY): mBatteryStats.noteScanWifiLockReleased(uid);
+            }
+        } catch (RemoteException e) {
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        
         updateWifiState();
         return result;
     }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index e4bd3c3..5623b02 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -1294,7 +1294,7 @@
             // Update Orientation after adding a window, only if the window needs to be
             // displayed right away
             if (win.isVisibleOrAdding()) {
-                if (updateOrientationFromAppTokens(null) != null) {
+                if (updateOrientationFromAppTokens(null, null) != null) {
                     sendNewConfiguration();
                 }
             }
@@ -1663,7 +1663,7 @@
             if (assignLayers) {
                 assignLayersLocked();
             }
-            newConfig = updateOrientationFromAppTokensLocked(null);
+            newConfig = updateOrientationFromAppTokensLocked(null, null);
             performLayoutAndPlaceSurfacesLocked();
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
@@ -2079,6 +2079,11 @@
             while (pos >= 0) {
                 AppWindowToken wtoken = mAppTokens.get(pos);
                 pos--;
+                // if we're about to tear down this window, don't use it for orientation
+                if (!wtoken.hidden && wtoken.hiddenRequested) {
+                    continue;
+                }
+
                 if (!haveGroup) {
                     // We ignore any hidden applications on the top.
                     if (wtoken.hiddenRequested || wtoken.willBeHidden) {
@@ -2119,11 +2124,11 @@
     }
     
     public Configuration updateOrientationFromAppTokens(
-        IBinder freezeThisOneIfNeeded) {
+            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
         Configuration config;
         long ident = Binder.clearCallingIdentity();
         synchronized(mWindowMap) {
-            config = updateOrientationFromAppTokensLocked(freezeThisOneIfNeeded);
+            config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded);
         }
         if (config != null) {
             mLayoutNeeded = true;
@@ -2141,7 +2146,7 @@
      * android.os.IBinder)
      */
     Configuration updateOrientationFromAppTokensLocked(
-            IBinder freezeThisOneIfNeeded) {
+            Configuration appConfig, IBinder freezeThisOneIfNeeded) {
         boolean changed = false;
         long ident = Binder.clearCallingIdentity();
         try {
@@ -2170,6 +2175,15 @@
                     return computeNewConfiguration();
                 }
             }
+
+            // No obvious action we need to take, but if our current
+            // state mismatches the activity maanager's, update it
+            if (appConfig != null) {
+                Configuration wmConfig = computeNewConfiguration();
+                if (wmConfig.diff(appConfig) != 0) {
+                    return wmConfig;
+                }
+            }
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -4053,7 +4067,7 @@
         if (downTime == 0) downTime = eventTime;
 
         KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
-                deviceId, scancode);
+                deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
 
         boolean result = dispatchKey(newEvent, Binder.getCallingPid(), Binder.getCallingUid());
         if (sync) {
@@ -5107,7 +5121,7 @@
                         if (DEBUG_INPUT) Log.v(
                             TAG, "Key repeat: count=" + keyRepeatCount
                             + ", next @ " + nextKeyTime);
-                        dispatchKey(new KeyEvent(lastKey, curTime, keyRepeatCount), 0, 0);
+                        dispatchKey(KeyEvent.changeTimeRepeat(lastKey, curTime, keyRepeatCount), 0, 0);
                         
                     } else {
                         curTime = SystemClock.uptimeMillis();
@@ -5361,6 +5375,7 @@
         final Session mSession;
         final IWindow mClient;
         WindowToken mToken;
+        WindowToken mRootToken;
         AppWindowToken mAppToken;
         AppWindowToken mTargetAppToken;
         final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
@@ -5573,6 +5588,7 @@
                 }
                 appToken = parent;
             }
+            mRootToken = appToken;
             mAppToken = appToken.appWindowToken;
 
             mSurface = null;
@@ -6231,7 +6247,7 @@
          */
         boolean isVisibleNow() {
             return mSurface != null && mPolicyVisibility && !mAttachedHidden
-                    && !mToken.hidden && !mExiting && !mDestroying;
+                    && !mRootToken.hidden && !mExiting && !mDestroying;
         }
 
         /**
@@ -6272,7 +6288,7 @@
             final AppWindowToken atoken = mAppToken;
             final boolean animating = atoken != null ? atoken.animating : false;
             return mSurface != null && mPolicyVisibility && !mDestroying
-                    && ((!mAttachedHidden && !mToken.hidden)
+                    && ((!mAttachedHidden && !mRootToken.hidden)
                             || mAnimating || animating);
         }
 
@@ -6431,6 +6447,7 @@
                   + " mLastLayer=" + mLastLayer);
             pw.println(prefix + "mSurface=" + mSurface);
             pw.println(prefix + "mToken=" + mToken);
+            pw.println(prefix + "mRootToken=" + mRootToken);
             pw.println(prefix + "mAppToken=" + mAppToken);
             pw.println(prefix + "mTargetAppToken=" + mTargetAppToken);
             pw.println(prefix + "mViewVisibility=0x" + Integer.toHexString(mViewVisibility)
@@ -7279,7 +7296,7 @@
                 }
                 
                 case COMPUTE_AND_SEND_NEW_CONFIGURATION: {
-                    if (updateOrientationFromAppTokens(null) != null) {
+                    if (updateOrientationFromAppTokens(null, null) != null) {
                         sendNewConfiguration();
                     }
                     break;
@@ -7458,7 +7475,7 @@
     
                 boolean gone = win.mViewVisibility == View.GONE
                         || !win.mRelayoutCalled
-                        || win.mToken.hidden;
+                        || win.mRootToken.hidden;
 
                 // If this view is GONE, then skip it -- keep the current
                 // frame, and let the caller know so they can ignore it
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 9d720d1..9e2ecba 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -121,6 +121,7 @@
     static final boolean DEBUG_VISBILITY = localLOGV || false;
     static final boolean DEBUG_PROCESSES = localLOGV || false;
     static final boolean DEBUG_USER_LEAVING = localLOGV || false;
+    static final boolean DEBUG_RESULTS = localLOGV || false;
     static final boolean VALIDATE_TOKENS = false;
     static final boolean SHOW_ACTIVITY_START_TIME = true;
     
@@ -1536,6 +1537,7 @@
         // just restarting it anyway.
         if (checkConfig) {
             Configuration config = mWindowManager.updateOrientationFromAppTokens(
+                    mConfiguration,
                     r.mayFreezeScreenLocked(app) ? r : null);
             updateConfigurationLocked(config, r);
         }
@@ -2336,6 +2338,7 @@
             // Have the window manager re-evaluate the orientation of
             // the screen based on the new activity order.
             Configuration config = mWindowManager.updateOrientationFromAppTokens(
+                    mConfiguration,
                     next.mayFreezeScreenLocked(next.app) ? next : null);
             if (config != null) {
                 next.frozenBeforeDestroy = true;
@@ -2364,7 +2367,7 @@
                 if (a != null) {
                     final int N = a.size();
                     if (!next.finishing && N > 0) {
-                        if (localLOGV) Log.v(
+                        if (DEBUG_RESULTS) Log.v(
                                 TAG, "Delivering results to " + next
                                 + ": " + a);
                         next.app.thread.scheduleSendResult(next, a);
@@ -2701,7 +2704,7 @@
         HistoryRecord resultRecord = null;
         if (resultTo != null) {
             int index = indexOfTokenLocked(resultTo, false);
-            if (localLOGV) Log.v(
+            if (DEBUG_RESULTS) Log.v(
                 TAG, "Sending result to " + resultTo + " (index " + index + ")");
             if (index >= 0) {
                 sourceRecord = (HistoryRecord)mHistory.get(index);
@@ -3358,6 +3361,7 @@
             final long origId = Binder.clearCallingIdentity();
             mWindowManager.setAppOrientation(r, requestedOrientation);
             Configuration config = mWindowManager.updateOrientationFromAppTokens(
+                    mConfiguration,
                     r.mayFreezeScreenLocked(r.app) ? r : null);
             if (config != null) {
                 r.frozenBeforeDestroy = true;
@@ -3486,7 +3490,7 @@
         // send the result
         HistoryRecord resultTo = r.resultTo;
         if (resultTo != null) {
-            if (localLOGV) Log.v(TAG, "Adding result to " + resultTo);
+            if (DEBUG_RESULTS) Log.v(TAG, "Adding result to " + resultTo);
             if (r.info.applicationInfo.uid > 0) {
                 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
                         r.packageName, resultData, r);
@@ -3652,6 +3656,9 @@
                     data, r);
         }
 
+        if (DEBUG_RESULTS) Log.v(TAG, "Send activity result to " + r
+                + " : who=" + resultWho + " req=" + requestCode
+                + " res=" + resultCode + " data=" + data);
         if (mResumedActivity == r && r.app != null && r.app.thread != null) {
             try {
                 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
@@ -9013,7 +9020,7 @@
         }
 
         r.app = app;
-        r.restartTime = SystemClock.uptimeMillis();
+        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
 
         app.services.add(r);
         bumpServiceExecutingLocked(r);
@@ -10133,8 +10140,19 @@
             // installed.  Maybe in the future we want to have a special install
             // broadcast or such for apps, but we'd like to deliberately make
             // this decision.
-            String skipPackage = (intent.ACTION_PACKAGE_ADDED.equals(
-                    intent.getAction()) && intent.getData() != null)
+            boolean skip = false;
+            if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
+                // If this is replacing an existing package, then we allow it
+                // to see the broadcast for it to restart itself.
+                if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                    skip = true;
+                }
+            } else if (intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())) {
+                skip = true;
+            } else if (intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
+                skip = true;
+            }
+            String skipPackage = (skip && intent.getData() != null)
                     ? intent.getData().getSchemeSpecificPart()
                     : null;
             if (skipPackage != null && receivers != null) {
@@ -11306,6 +11324,10 @@
                         // XXX should compute this based on the max of
                         // all connected clients.
                         ConnectionRecord cr = kt.next();
+                        if (cr.binding.client == app) {
+                            // Binding to ourself is not interesting.
+                            continue;
+                        }
                         if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
                             ProcessRecord client = cr.binding.client;
                             int myHiddenAdj = hiddenAdj;
@@ -11352,6 +11374,10 @@
                     Iterator<ProcessRecord> kt = cpr.clients.iterator();
                     while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
                         ProcessRecord client = kt.next();
+                        if (client == app) {
+                            // Being our own client is not interesting.
+                            continue;
+                        }
                         int myHiddenAdj = hiddenAdj;
                         if (myHiddenAdj > client.hiddenAdj) {
                             if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 27d0401..cc9a0af 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -148,14 +148,70 @@
             mStats.notePhoneOffLocked();
         }
     }
+    
+    public void noteWifiOn() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteWifiOnLocked();
+        }
+    }
+    
+    public void noteWifiOff() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteWifiOffLocked();
+        }
+    }
+    
+    public void noteBluetoothOn() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteBluetoothOnLocked();
+        }
+    }
+    
+    public void noteBluetoothOff() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteBluetoothOffLocked();
+        }
+    }
+    
+    public void noteFullWifiLockAcquired(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteFullWifiLockAcquiredLocked(uid);
+        }
+    }
+    
+    public void noteFullWifiLockReleased(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteFullWifiLockReleasedLocked(uid);
+        }
+    }
+    
+    public void noteScanWifiLockAcquired(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteScanWifiLockAcquiredLocked(uid);
+        }
+    }
+    
+    public void noteScanWifiLockReleased(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteScanWifiLockReleasedLocked(uid);
+        }
+    }
 
     public boolean isOnBattery() {
         return mStats.isOnBattery();
     }
     
-    public void setOnBattery(boolean onBattery) {
+    public void setOnBattery(boolean onBattery, int level) {
         enforceCallingPermission();
-        mStats.setOnBattery(onBattery);
+        mStats.setOnBattery(onBattery, level);
     }
     
     public long getAwakeTimeBattery() {
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 8433227..36d1465 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -24,6 +24,7 @@
 import android.app.AlertDialog;
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothError;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothIntent;
 import android.content.BroadcastReceiver;
@@ -222,8 +223,7 @@
             else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                 updateBattery(intent);
             }
-            else if (action.equals(BluetoothIntent.ENABLED_ACTION) ||
-                    action.equals(BluetoothIntent.DISABLED_ACTION) ||
+            else if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION) ||
                     action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION) ||
                     action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) {
                 updateBluetooth(intent);
@@ -345,8 +345,7 @@
         filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
         filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
-        filter.addAction(BluetoothIntent.ENABLED_ACTION);
-        filter.addAction(BluetoothIntent.DISABLED_ACTION);
+        filter.addAction(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION);
         filter.addAction(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION);
         filter.addAction(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
@@ -796,10 +795,10 @@
         int iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth;
 
         String action = intent.getAction();
-        if (action.equals(BluetoothIntent.DISABLED_ACTION)) {
-            mBluetoothEnabled = false;
-        } else if (action.equals(BluetoothIntent.ENABLED_ACTION)) {
-            mBluetoothEnabled = true;
+        if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION)) {
+            int state = intent.getIntExtra(BluetoothIntent.BLUETOOTH_STATE,
+                                           BluetoothError.ERROR);
+            mBluetoothEnabled = state == BluetoothDevice.BLUETOOTH_STATE_ON;
         } else if (action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION)) {
             mBluetoothHeadsetState = intent.getIntExtra(BluetoothIntent.HEADSET_STATE,
                     BluetoothHeadset.STATE_ERROR);
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 5442e1d..5336e27 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -57,6 +57,8 @@
 import android.widget.RemoteViews;
 import android.widget.ScrollView;
 import android.widget.TextView;
+import android.widget.FrameLayout;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -1476,9 +1478,11 @@
 
         /// ---------- Expanded View --------------
         pixelFormat = PixelFormat.TRANSLUCENT;
-        bg = mExpandedView.getBackground();
-        if (bg != null) {
-            pixelFormat = bg.getOpacity();
+        if (false) {
+            bg = mExpandedView.getBackground();
+            if (bg != null) {
+                pixelFormat = bg.getOpacity();
+            }
         }
 
         lp = mExpandedDialog.getWindow().getAttributes();
@@ -1490,11 +1494,13 @@
         lp.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                | WindowManager.LayoutParams.FLAG_DITHER;
         lp.format = pixelFormat;
         lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
         lp.setTitle("StatusBarExpanded");
         mExpandedDialog.getWindow().setAttributes(lp);
+        mExpandedDialog.getWindow().setFormat(pixelFormat);
         mExpandedParams = lp;
 
         mExpandedDialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
@@ -1503,7 +1509,8 @@
                                            ViewGroup.LayoutParams.WRAP_CONTENT));
         mExpandedDialog.show();
         mExpandedDialog.hide();
-        View hack = (View)mExpandedView.getParent();
+        FrameLayout hack = (FrameLayout)mExpandedView.getParent();
+        hack.setForeground(null);
     }
 
     void setDateViewVisibility(boolean visible, int anim) {
diff --git a/services/java/com/android/server/status/TrackingPatternView.java b/services/java/com/android/server/status/TrackingPatternView.java
new file mode 100644
index 0000000..0ae9984
--- /dev/null
+++ b/services/java/com/android/server/status/TrackingPatternView.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+package com.android.server.status;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Paint;
+import android.graphics.Canvas;
+
+public class TrackingPatternView extends View {
+    private Bitmap mTexture;
+    private Paint mPaint;
+    private int mTextureWidth;
+    private int mTextureHeight;
+    
+    public TrackingPatternView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        mTexture = BitmapFactory.decodeResource(getResources(), 
+                com.android.internal.R.drawable.status_bar_background);
+        mTextureWidth = mTexture.getWidth();
+        mTextureHeight = mTexture.getHeight();
+
+        mPaint = new Paint();
+        mPaint.setDither(false);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        final Bitmap texture = mTexture;
+        final Paint paint = mPaint;
+
+        final int width = getWidth();
+        final int height = getHeight();
+
+        final int textureWidth = mTextureWidth;
+        final int textureHeight = mTextureHeight;
+
+        Log.d("TrackingPatternView", "width=" + width + " textureWidth=" + textureWidth);
+
+        int x = 0;
+        int y;
+
+        while (x < width) {
+            y = 0;
+            while (y < height) {
+                canvas.drawBitmap(texture, x, y, paint);
+                y += textureHeight;
+            }
+            x += textureWidth;
+        }
+    }
+}