Merge "Import translations. DO NOT MERGE"
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index f523b55..62ed697 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.os.BatteryStats;
 import android.os.IBinder;
 import com.android.internal.app.IUsageStats;
 import com.android.internal.os.PkgUsageStats;
@@ -2210,7 +2211,7 @@
         pw.println();
         dumpService(pw, fd, "package", new String[] { packageName});
         pw.println();
-        dumpService(pw, fd, "batteryinfo", new String[] { packageName});
+        dumpService(pw, fd, BatteryStats.SERVICE_NAME, new String[] { packageName});
         pw.flush();
     }
 
diff --git a/core/java/android/hardware/display/WifiDisplay.java b/core/java/android/hardware/display/WifiDisplay.java
index 339fd6b..af5a84e 100644
--- a/core/java/android/hardware/display/WifiDisplay.java
+++ b/core/java/android/hardware/display/WifiDisplay.java
@@ -33,7 +33,9 @@
     private final String mDeviceAddress;
     private final String mDeviceName;
     private final String mDeviceAlias;
+    private final boolean mIsAvailable;
     private final boolean mCanConnect;
+    private final boolean mIsRemembered;
 
     public static final WifiDisplay[] EMPTY_ARRAY = new WifiDisplay[0];
 
@@ -42,9 +44,11 @@
             String deviceAddress = in.readString();
             String deviceName = in.readString();
             String deviceAlias = in.readString();
+            boolean isAvailable = (in.readInt() != 0);
             boolean canConnect = (in.readInt() != 0);
-            return new WifiDisplay(deviceAddress, deviceName,
-                    deviceAlias, canConnect);
+            boolean isRemembered = (in.readInt() != 0);
+            return new WifiDisplay(deviceAddress, deviceName, deviceAlias,
+                    isAvailable, canConnect, isRemembered);
         }
 
         public WifiDisplay[] newArray(int size) {
@@ -52,12 +56,8 @@
         }
     };
 
-    public WifiDisplay(String deviceAddress, String deviceName, String deviceAlias) {
-        this(deviceAddress, deviceName, deviceAlias, false);
-    }
-
-    public WifiDisplay(String deviceAddress, String deviceName,
-                       String deviceAlias, boolean canConnect) {
+    public WifiDisplay(String deviceAddress, String deviceName, String deviceAlias,
+            boolean available, boolean canConnect, boolean remembered) {
         if (deviceAddress == null) {
             throw new IllegalArgumentException("deviceAddress must not be null");
         }
@@ -68,7 +68,9 @@
         mDeviceAddress = deviceAddress;
         mDeviceName = deviceName;
         mDeviceAlias = deviceAlias;
+        mIsAvailable = available;
         mCanConnect = canConnect;
+        mIsRemembered = remembered;
     }
 
     /**
@@ -97,13 +99,27 @@
     }
 
     /**
-     * Gets the availability of the Wifi display device.
+     * Returns true if device is available, false otherwise.
+     */
+    public boolean isAvailable() {
+        return mIsAvailable;
+    }
+
+    /**
+     * Returns true if device can be connected to (not in use), false otherwise.
      */
     public boolean canConnect() {
         return mCanConnect;
     }
 
     /**
+     * Returns true if device has been remembered, false otherwise.
+     */
+    public boolean isRemembered() {
+        return mIsRemembered;
+    }
+
+    /**
      * Gets the name to show in the UI.
      * Uses the device alias if available, otherwise uses the device name.
      */
@@ -116,12 +132,15 @@
         return o instanceof WifiDisplay && equals((WifiDisplay)o);
     }
 
+    /**
+     * Returns true if the two displays have the same identity (address, name and alias).
+     * This method does not compare the current status of the displays.
+     */
     public boolean equals(WifiDisplay other) {
         return other != null
                 && mDeviceAddress.equals(other.mDeviceAddress)
                 && mDeviceName.equals(other.mDeviceName)
-                && Objects.equal(mDeviceAlias, other.mDeviceAlias)
-                && (mCanConnect == other.mCanConnect);
+                && Objects.equal(mDeviceAlias, other.mDeviceAlias);
     }
 
     /**
@@ -144,7 +163,9 @@
         dest.writeString(mDeviceAddress);
         dest.writeString(mDeviceName);
         dest.writeString(mDeviceAlias);
+        dest.writeInt(mIsAvailable ? 1 : 0);
         dest.writeInt(mCanConnect ? 1 : 0);
+        dest.writeInt(mIsRemembered ? 1 : 0);
     }
 
     @Override
@@ -159,7 +180,8 @@
         if (mDeviceAlias != null) {
             result += ", alias " + mDeviceAlias;
         }
-        result += ", canConnect " + mCanConnect;
+        result += ", isAvailable " + mIsAvailable + ", canConnect " + mCanConnect
+                + ", isRemembered " + mIsRemembered;
         return result;
     }
 }
diff --git a/core/java/android/hardware/display/WifiDisplayStatus.java b/core/java/android/hardware/display/WifiDisplayStatus.java
index f7e72c4..77acdc0 100644
--- a/core/java/android/hardware/display/WifiDisplayStatus.java
+++ b/core/java/android/hardware/display/WifiDisplayStatus.java
@@ -20,6 +20,8 @@
 import android.os.Parcelable;
 
 import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Describes the current global state of Wifi display connectivity, including the
@@ -35,8 +37,7 @@
     private final int mScanState;
     private final int mActiveDisplayState;
     private final WifiDisplay mActiveDisplay;
-    private final WifiDisplay[] mAvailableDisplays;
-    private final WifiDisplay[] mRememberedDisplays;
+    private final WifiDisplay[] mDisplays;
 
     /** Feature state: Wifi display is not available on this device. */
     public static final int FEATURE_STATE_UNAVAILABLE = 0;
@@ -70,18 +71,13 @@
                 activeDisplay = WifiDisplay.CREATOR.createFromParcel(in);
             }
 
-            WifiDisplay[] availableDisplays = WifiDisplay.CREATOR.newArray(in.readInt());
-            for (int i = 0; i < availableDisplays.length; i++) {
-                availableDisplays[i] = WifiDisplay.CREATOR.createFromParcel(in);
-            }
-
-            WifiDisplay[] rememberedDisplays = WifiDisplay.CREATOR.newArray(in.readInt());
-            for (int i = 0; i < rememberedDisplays.length; i++) {
-                rememberedDisplays[i] = WifiDisplay.CREATOR.createFromParcel(in);
+            WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(in.readInt());
+            for (int i = 0; i < displays.length; i++) {
+                displays[i] = WifiDisplay.CREATOR.createFromParcel(in);
             }
 
             return new WifiDisplayStatus(featureState, scanState, activeDisplayState,
-                    activeDisplay, availableDisplays, rememberedDisplays);
+                    activeDisplay, displays);
         }
 
         public WifiDisplayStatus[] newArray(int size) {
@@ -91,25 +87,20 @@
 
     public WifiDisplayStatus() {
         this(FEATURE_STATE_UNAVAILABLE, SCAN_STATE_NOT_SCANNING, DISPLAY_STATE_NOT_CONNECTED,
-                null, WifiDisplay.EMPTY_ARRAY, WifiDisplay.EMPTY_ARRAY);
+                null, WifiDisplay.EMPTY_ARRAY);
     }
 
     public WifiDisplayStatus(int featureState, int scanState,
-            int activeDisplayState, WifiDisplay activeDisplay,
-            WifiDisplay[] availableDisplays, WifiDisplay[] rememberedDisplays) {
-        if (availableDisplays == null) {
-            throw new IllegalArgumentException("availableDisplays must not be null");
-        }
-        if (rememberedDisplays == null) {
-            throw new IllegalArgumentException("rememberedDisplays must not be null");
+            int activeDisplayState, WifiDisplay activeDisplay, WifiDisplay[] displays) {
+        if (displays == null) {
+            throw new IllegalArgumentException("displays must not be null");
         }
 
         mFeatureState = featureState;
         mScanState = scanState;
         mActiveDisplayState = activeDisplayState;
         mActiveDisplay = activeDisplay;
-        mAvailableDisplays = availableDisplays;
-        mRememberedDisplays = rememberedDisplays;
+        mDisplays = displays;
     }
 
     /**
@@ -152,24 +143,12 @@
     }
 
     /**
-     * Gets the list of all available Wifi displays as reported by the most recent
-     * scan, never null.
-     * <p>
-     * Some of these displays may already be remembered, others may be unknown.
-     * </p>
+     * Gets the list of Wifi displays, returns a combined list of all available
+     * Wifi displays as reported by the most recent scan, and all remembered 
+     * Wifi displays (not necessarily available at the time).
      */
-    public WifiDisplay[] getAvailableDisplays() {
-        return mAvailableDisplays;
-    }
-
-    /**
-     * Gets the list of all remembered Wifi displays, never null.
-     * <p>
-     * Not all remembered displays will necessarily be available.
-     * </p>
-     */
-    public WifiDisplay[] getRememberedDisplays() {
-        return mRememberedDisplays;
+    public WifiDisplay[] getDisplays() {
+        return mDisplays;
     }
 
     @Override
@@ -185,13 +164,8 @@
             dest.writeInt(0);
         }
 
-        dest.writeInt(mAvailableDisplays.length);
-        for (WifiDisplay display : mAvailableDisplays) {
-            display.writeToParcel(dest, flags);
-        }
-
-        dest.writeInt(mRememberedDisplays.length);
-        for (WifiDisplay display : mRememberedDisplays) {
+        dest.writeInt(mDisplays.length);
+        for (WifiDisplay display : mDisplays) {
             display.writeToParcel(dest, flags);
         }
     }
@@ -208,8 +182,7 @@
                 + ", scanState=" + mScanState
                 + ", activeDisplayState=" + mActiveDisplayState
                 + ", activeDisplay=" + mActiveDisplay
-                + ", availableDisplays=" + Arrays.toString(mAvailableDisplays)
-                + ", rememberedDisplays=" + Arrays.toString(mRememberedDisplays)
+                + ", displays=" + Arrays.toString(mDisplays)
                 + "}";
     }
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index fef1818..7c09e89c 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -41,7 +41,10 @@
 public abstract class BatteryStats implements Parcelable {
 
     private static final boolean LOCAL_LOGV = false;
-    
+
+    /** @hide */
+    public static final String SERVICE_NAME = "batterystats";
+
     /**
      * A constant indicating a partial wake lock timer.
      */
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d40eb64..3e2d8d3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3970,6 +3970,9 @@
     <!-- Status message for remote routes that are not available for connection right now -->
     <string name="media_route_status_not_available">Not available</string>
 
+    <!-- Status message for a remote route that is in use (and thus unavailabe) right now -->
+    <string name="media_route_status_in_use">In use</string>
+
     <!-- Display manager service -->
 
     <!-- Name of the built-in display.  [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d33a6fa..5680ce4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -850,6 +850,7 @@
   <java-symbol type="string" name="media_route_status_connecting" />
   <java-symbol type="string" name="media_route_status_available" />
   <java-symbol type="string" name="media_route_status_not_available" />
+  <java-symbol type="string" name="media_route_status_in_use" />
   <java-symbol type="string" name="owner_name" />
   <java-symbol type="string" name="config_chooseAccountActivity" />
   <java-symbol type="string" name="config_chooseTypeAndAccountActivity" />
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index d653d94..420a195 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -876,44 +876,45 @@
         boolean wantScan = false;
         boolean blockScan = false;
         WifiDisplay[] oldDisplays = oldStatus != null ?
-                oldStatus.getRememberedDisplays() : WifiDisplay.EMPTY_ARRAY;
+                oldStatus.getDisplays() : WifiDisplay.EMPTY_ARRAY;
         WifiDisplay[] newDisplays;
-        WifiDisplay[] availableDisplays;
         WifiDisplay activeDisplay;
 
         if (newStatus.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) {
-            newDisplays = newStatus.getRememberedDisplays();
-            availableDisplays = newStatus.getAvailableDisplays();
+            newDisplays = newStatus.getDisplays();
             activeDisplay = newStatus.getActiveDisplay();
         } else {
-            newDisplays = availableDisplays = WifiDisplay.EMPTY_ARRAY;
+            newDisplays = WifiDisplay.EMPTY_ARRAY;
             activeDisplay = null;
         }
 
         for (int i = 0; i < newDisplays.length; i++) {
             final WifiDisplay d = newDisplays[i];
-            final boolean available = findMatchingDisplay(d, availableDisplays) != null;
-            RouteInfo route = findWifiDisplayRoute(d);
-            if (route == null) {
-                route = makeWifiDisplayRoute(d, available);
-                addRouteStatic(route);
-                wantScan = true;
-            } else {
-                updateWifiDisplayRoute(route, d, available, newStatus);
-            }
-            if (d.equals(activeDisplay)) {
-                selectRouteStatic(route.getSupportedTypes(), route);
+            if (d.isRemembered()) {
+                RouteInfo route = findWifiDisplayRoute(d);
+                if (route == null) {
+                    route = makeWifiDisplayRoute(d, newStatus);
+                    addRouteStatic(route);
+                    wantScan = true;
+                } else {
+                    updateWifiDisplayRoute(route, d, newStatus);
+                }
+                if (d.equals(activeDisplay)) {
+                    selectRouteStatic(route.getSupportedTypes(), route);
 
-                // Don't scan if we're already connected to a wifi display,
-                // the scanning process can cause a hiccup with some configurations.
-                blockScan = true;
+                    // Don't scan if we're already connected to a wifi display,
+                    // the scanning process can cause a hiccup with some configurations.
+                    blockScan = true;
+                }
             }
         }
         for (int i = 0; i < oldDisplays.length; i++) {
             final WifiDisplay d = oldDisplays[i];
-            final WifiDisplay newDisplay = findMatchingDisplay(d, newDisplays);
-            if (newDisplay == null) {
-                removeRoute(findWifiDisplayRoute(d));
+            if (d.isRemembered()) {
+                final WifiDisplay newDisplay = findMatchingDisplay(d, newDisplays);
+                if (newDisplay == null || !newDisplay.isRemembered()) {
+                    removeRoute(findWifiDisplayRoute(d));
+                }
             }
         }
 
@@ -924,42 +925,20 @@
         sStatic.mLastKnownWifiDisplayStatus = newStatus;
     }
 
-    static RouteInfo makeWifiDisplayRoute(WifiDisplay display, boolean available) {
-        final RouteInfo newRoute = new RouteInfo(sStatic.mSystemCategory);
-        newRoute.mDeviceAddress = display.getDeviceAddress();
-        newRoute.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO;
-        newRoute.mVolumeHandling = RouteInfo.PLAYBACK_VOLUME_FIXED;
-        newRoute.mPlaybackType = RouteInfo.PLAYBACK_TYPE_REMOTE;
-
-        newRoute.setStatusCode(available ?
-                RouteInfo.STATUS_AVAILABLE : RouteInfo.STATUS_CONNECTING);
-        newRoute.mEnabled = available;
-
-        newRoute.mName = display.getFriendlyDisplayName();
-        newRoute.mDescription = sStatic.mResources.getText(
-                com.android.internal.R.string.wireless_display_route_description);
-
-        newRoute.mPresentationDisplay = choosePresentationDisplayForRoute(newRoute,
-                sStatic.getAllPresentationDisplays());
-        return newRoute;
-    }
-
-    private static void updateWifiDisplayRoute(RouteInfo route, WifiDisplay display,
-            boolean available, WifiDisplayStatus wifiDisplayStatus) {
-        final boolean isScanning =
-                wifiDisplayStatus.getScanState() == WifiDisplayStatus.SCAN_STATE_SCANNING;
-
-        boolean changed = false;
+    static int getWifiDisplayStatusCode(WifiDisplay d, WifiDisplayStatus wfdStatus) {
         int newStatus = RouteInfo.STATUS_NONE;
 
-        if (available) {
-            newStatus = isScanning ? RouteInfo.STATUS_SCANNING : RouteInfo.STATUS_AVAILABLE;
+        if (wfdStatus.getScanState() == WifiDisplayStatus.SCAN_STATE_SCANNING) {
+            newStatus = RouteInfo.STATUS_SCANNING;
+        } else if (d.isAvailable()) {
+            newStatus = d.canConnect() ?
+                    RouteInfo.STATUS_AVAILABLE: RouteInfo.STATUS_IN_USE;
         } else {
             newStatus = RouteInfo.STATUS_NOT_AVAILABLE;
         }
 
-        if (display.equals(wifiDisplayStatus.getActiveDisplay())) {
-            final int activeState = wifiDisplayStatus.getActiveDisplayState();
+        if (d.equals(wfdStatus.getActiveDisplay())) {
+            final int activeState = wfdStatus.getActiveDisplayState();
             switch (activeState) {
                 case WifiDisplayStatus.DISPLAY_STATE_CONNECTED:
                     newStatus = RouteInfo.STATUS_NONE;
@@ -973,22 +952,51 @@
             }
         }
 
+        return newStatus;
+    }
+
+    static boolean isWifiDisplayEnabled(WifiDisplay d, WifiDisplayStatus wfdStatus) {
+        return d.isAvailable() && (d.canConnect() || d.equals(wfdStatus.getActiveDisplay()));
+    }
+
+    static RouteInfo makeWifiDisplayRoute(WifiDisplay display, WifiDisplayStatus wfdStatus) {
+        final RouteInfo newRoute = new RouteInfo(sStatic.mSystemCategory);
+        newRoute.mDeviceAddress = display.getDeviceAddress();
+        newRoute.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO;
+        newRoute.mVolumeHandling = RouteInfo.PLAYBACK_VOLUME_FIXED;
+        newRoute.mPlaybackType = RouteInfo.PLAYBACK_TYPE_REMOTE;
+
+        newRoute.setStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
+        newRoute.mEnabled = isWifiDisplayEnabled(display, wfdStatus);
+        newRoute.mName = display.getFriendlyDisplayName();
+        newRoute.mDescription = sStatic.mResources.getText(
+                com.android.internal.R.string.wireless_display_route_description);
+
+        newRoute.mPresentationDisplay = choosePresentationDisplayForRoute(newRoute,
+                sStatic.getAllPresentationDisplays());
+        return newRoute;
+    }
+
+    private static void updateWifiDisplayRoute(
+            RouteInfo route, WifiDisplay display, WifiDisplayStatus wfdStatus) {
+        boolean changed = false;
         final String newName = display.getFriendlyDisplayName();
         if (!route.getName().equals(newName)) {
             route.mName = newName;
             changed = true;
         }
 
-        changed |= route.mEnabled != available;
-        route.mEnabled = available;
+        boolean enabled = isWifiDisplayEnabled(display, wfdStatus);
+        changed |= route.mEnabled != enabled;
+        route.mEnabled = enabled;
 
-        changed |= route.setStatusCode(newStatus);
+        changed |= route.setStatusCode(getWifiDisplayStatusCode(display, wfdStatus));
 
         if (changed) {
             dispatchRouteChanged(route);
         }
 
-        if (!available && route == sStatic.mSelectedRoute) {
+        if (!enabled && route == sStatic.mSelectedRoute) {
             // Oops, no longer available. Reselect the default.
             final RouteInfo defaultRoute = sStatic.mDefaultAudioVideo;
             selectRouteStatic(defaultRoute.getSupportedTypes(), defaultRoute);
@@ -1069,6 +1077,7 @@
         /** @hide */ public static final int STATUS_CONNECTING = 2;
         /** @hide */ public static final int STATUS_AVAILABLE = 3;
         /** @hide */ public static final int STATUS_NOT_AVAILABLE = 4;
+        /** @hide */ public static final int STATUS_IN_USE = 5;
 
         private Object mTag;
 
@@ -1180,6 +1189,9 @@
                     case STATUS_NOT_AVAILABLE:
                         resId = com.android.internal.R.string.media_route_status_not_available;
                         break;
+                    case STATUS_IN_USE:
+                        resId = com.android.internal.R.string.media_route_status_in_use;
+                        break;
                 }
                 mStatus = resId != 0 ? sStatic.mResources.getText(resId) : null;
                 return true;
diff --git a/packages/SystemUI/res/values-land/refs.xml b/packages/SystemUI/res/values-land/refs.xml
new file mode 100644
index 0000000..f5e79b9
--- /dev/null
+++ b/packages/SystemUI/res/values-land/refs.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, 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.
+*/
+-->
+<resources>
+    <item type="string" name="hideybar_confirmation_message">@string/hideybar_confirmation_message_long</item>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-port/refs.xml b/packages/SystemUI/res/values-sw600dp-port/refs.xml
new file mode 100644
index 0000000..f5e79b9
--- /dev/null
+++ b/packages/SystemUI/res/values-sw600dp-port/refs.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, 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.
+*/
+-->
+<resources>
+    <item type="string" name="hideybar_confirmation_message">@string/hideybar_confirmation_message_long</item>
+</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 9498fe4..129e0e8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -24,17 +24,6 @@
          all of the currently visible notifications. [CHAR LIMIT=10]-->
     <string name="status_bar_clear_all_button">Clear</string>
 
-    <!-- The text for the button in the notification window-shade that turns
-         on do not disturb mode, where notifications no longer show their ticker,
-         no sound plays, and no icons are visible.  The windowshade continues to show
-         the notifications. [CHAR LIMIT=25]-->
-    <string name="status_bar_do_not_disturb_button">Do not disturb</string>
-
-    <!-- The text for the button in the notification window-shade that turns
-         off do not disturb mode.  After clicking this, notifications will be
-         shown again. [CHAR LIMIT=25] -->
-    <string name="status_bar_please_disturb_button">Show notifications</string>
-
     <!-- Title shown in recents popup for removing an application from the list -->
     <string name="status_bar_recent_remove_item_title">Remove from list</string>
 
@@ -436,13 +425,6 @@
          application -->
     <string name="status_bar_notification_inspect_item_title">App info</string>
 
-    <!-- Title for the pseudo-notification shown when notifications are disabled (do-not-disturb
-         mode) -->
-    <string name="notifications_off_title">Notifications off</string>
-
-    <!-- Content text for do-not-disturb mode notification -->
-    <string name="notifications_off_text">Tap here to turn notifications back on.</string>
-
     <!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is on. [CHAR LIMIT=NONE] -->
     <string name="accessibility_rotation_lock_off">Screen will rotate automatically.</string>
 
@@ -517,12 +499,9 @@
     <!-- Body of help text shown when the notification panel is pulled down for the very first time. [CHAR LIMIT=NONE] -->
     <string name="status_bar_help_text">Access them anytime by swiping down.\nSwipe down again for system controls.</string>
 
-    <!-- Toast bar message when hiding the navigation bar on bottom -->
-    <string name="hideybar_confirmation_message_bottom">Swipe up from bottom of screen to reveal system bar</string>
+    <!-- Toast bar message when hiding the navigation bar -->
+    <string name="hideybar_confirmation_message">Swipe edge of screen to reveal bar</string>
 
-    <!-- Shorter version of toast bar message when hiding the navigation bar on bottom -->
-    <string name="hideybar_confirmation_message_bottom_short">Swipe bottom of screen to reveal bar</string>
-
-    <!-- Toast bar message when hiding the navigation bar on right -->
-    <string name="hideybar_confirmation_message_right">Swipe from right of screen to reveal system bar</string>
+    <!-- Longer version of toast bar message when hiding the navigation bar (if room) -->
+    <string name="hideybar_confirmation_message_long">Swipe from edge of screen to reveal system bar</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DoNotDisturb.java b/packages/SystemUI/src/com/android/systemui/statusbar/DoNotDisturb.java
deleted file mode 100644
index 7520434..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DoNotDisturb.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2010 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.systemui.statusbar;
-
-import android.app.StatusBarManager;
-import android.content.Context;
-import android.content.SharedPreferences;
-
-import com.android.systemui.statusbar.policy.Prefs;
-
-public class DoNotDisturb implements SharedPreferences.OnSharedPreferenceChangeListener {
-    private Context mContext;
-    private StatusBarManager mStatusBar;
-    SharedPreferences mPrefs;
-    private boolean mDoNotDisturb;
-
-    public DoNotDisturb(Context context) {
-        mContext = context;
-        mStatusBar = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
-        mPrefs = Prefs.read(context);
-        mPrefs.registerOnSharedPreferenceChangeListener(this);
-        mDoNotDisturb = mPrefs.getBoolean(Prefs.DO_NOT_DISTURB_PREF, Prefs.DO_NOT_DISTURB_DEFAULT);
-        updateDisableRecord();
-    }
-
-    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
-        final boolean val = prefs.getBoolean(Prefs.DO_NOT_DISTURB_PREF,
-                Prefs.DO_NOT_DISTURB_DEFAULT);
-        if (val != mDoNotDisturb) {
-            mDoNotDisturb = val;
-            updateDisableRecord();
-        }
-    }
-
-    private void updateDisableRecord() {
-        final int disabled = StatusBarManager.DISABLE_NOTIFICATION_ICONS
-                | StatusBarManager.DISABLE_NOTIFICATION_ALERTS
-                | StatusBarManager.DISABLE_NOTIFICATION_TICKER;
-        mStatusBar.disable(mDoNotDisturb ? disabled : 0);
-    }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java
deleted file mode 100644
index 5ea17e7..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CarrierLabel.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2006 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.systemui.statusbar.phone;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.widget.TextView;
-
-import com.android.internal.telephony.TelephonyIntents;
-
-/**
- * This widget display an analogic clock with two hands for hours and
- * minutes.
- */
-public class CarrierLabel extends TextView {
-    private boolean mAttached;
-
-    public CarrierLabel(Context context) {
-        this(context, null);
-    }
-
-    public CarrierLabel(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public CarrierLabel(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        updateNetworkName(false, null, false, null);
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-
-        if (!mAttached) {
-            mAttached = true;
-            IntentFilter filter = new IntentFilter();
-            filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
-            getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
-        }
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        if (mAttached) {
-            getContext().unregisterReceiver(mIntentReceiver);
-            mAttached = false;
-        }
-    }
-
-    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
-                updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
-                        intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
-                        intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
-                        intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
-            }
-        }
-    };
-
-    void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) {
-        if (false) {
-            Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
-                    + " showPlmn=" + showPlmn + " plmn=" + plmn);
-        }
-        final String str;
-        // match logic in KeyguardStatusViewManager
-        final boolean plmnValid = showPlmn && !TextUtils.isEmpty(plmn);
-        final boolean spnValid = showSpn && !TextUtils.isEmpty(spn);
-        if (plmnValid && spnValid) {
-            str = plmn + "|" + spn;
-        } else if (plmnValid) {
-            str = plmn;
-        } else if (spnValid) {
-            str = spn;
-        } else {
-            str = "";
-        }
-        setText(str);
-    }
-
-
-}
-
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CloseDragHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CloseDragHandle.java
deleted file mode 100644
index ee01489..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CloseDragHandle.java
+++ /dev/null
@@ -1,53 +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.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.widget.LinearLayout;
-
-
-public class CloseDragHandle extends LinearLayout {
-    PhoneStatusBar mService;
-
-    public CloseDragHandle(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    /**
-     * Ensure that, if there is no target under us to receive the touch,
-     * that we process it ourself.  This makes sure that onInterceptTouchEvent()
-     * is always called for the entire gesture.
-     */
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            setPressed(true);
-        } else {
-            mService.interceptTouchEvent(event);
-        }
-        return true;
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent event) {
-        return mService.interceptTouchEvent(event)
-                ? true : super.onInterceptTouchEvent(event);
-    }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index a54c435..4b30c86 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1959,13 +1959,8 @@
     private void setHideybarConfirmationVisible(boolean visible) {
         if (DEBUG) Log.d(TAG, "setHideybarConfirmationVisible " + visible);
         if (visible && mHideybarConfirmation == null && !mHideybarConfirmationDismissed) {
-            // create the confirmation toast bar with the correct message for this config
-            float widthDp = mCurrentDisplaySize.x /
-                    (mDisplayMetrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT);
-            int msg = mNavigationBarView.isVertical() ?
-                    R.string.hideybar_confirmation_message_right :
-                    widthDp < 600 ? R.string.hideybar_confirmation_message_bottom_short :
-                    R.string.hideybar_confirmation_message_bottom;
+            // create the confirmation toast bar
+            int msg = R.string.hideybar_confirmation_message;
             mHideybarConfirmation = Toast.makeBar(mContext, msg, Toast.LENGTH_INFINITE)
                     .setAction(com.android.internal.R.string.ok, mHideybarConfirmationAction);
             View v = mHideybarConfirmation.getView();
@@ -1975,13 +1970,6 @@
                 // dismiss on outside touch if globally confirmed
                 v.setOnTouchListener(mDismissHideybarConfirmationOnTouchOutside);
             }
-            // position at the bottom like normal toasts, but use top gravity
-            // to avoid jumping around when showing/hiding the nav bar
-            v.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
-            int offsetY = mContext.getResources().getDimensionPixelSize(
-                    com.android.internal.R.dimen.toast_y_offset);
-            mHideybarConfirmation.setGravity(Gravity.TOP, 0,
-                    mCurrentDisplaySize.y - v.getMeasuredHeight() / 2 - offsetY);
             // show the confirmation
             mHideybarConfirmation.show();
         } else if (!visible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingPatternView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingPatternView.java
deleted file mode 100644
index 68807a0..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingPatternView.java
+++ /dev/null
@@ -1,68 +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.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.view.View;
-
-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;
-
-        int x = 0;
-        int y;
-
-        while (x < width) {
-            y = 0;
-            while (y < height) {
-                canvas.drawBitmap(texture, x, y, paint);
-                y += textureHeight;
-            }
-            x += textureWidth;
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
deleted file mode 100644
index 8bbe957..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2010 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.systemui.statusbar.policy;
-
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.AsyncTask;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.widget.CompoundButton;
-
-public class AirplaneModeController extends BroadcastReceiver
-        implements CompoundButton.OnCheckedChangeListener {
-    private static final String TAG = "StatusBar.AirplaneModeController";
-
-    private Context mContext;
-    private CompoundButton mCheckBox;
-
-    private boolean mAirplaneMode;
-
-    public AirplaneModeController(Context context, CompoundButton checkbox) {
-        mContext = context;
-        mAirplaneMode = getAirplaneMode();
-        mCheckBox = checkbox;
-        checkbox.setChecked(mAirplaneMode);
-        checkbox.setOnCheckedChangeListener(this);
-
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-        context.registerReceiver(this, filter);
-
-    }
-
-    public void release() {
-        mContext.unregisterReceiver(this);
-    }
-
-    public void onCheckedChanged(CompoundButton view, boolean checked) {
-        if (checked != mAirplaneMode) {
-            mAirplaneMode = checked;
-            unsafe(checked);
-        }
-    }
-
-    public void onReceive(Context context, Intent intent) {
-        if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) {
-            final boolean enabled = intent.getBooleanExtra("state", false);
-            if (enabled != mAirplaneMode) {
-                mAirplaneMode = enabled;
-                mCheckBox.setChecked(enabled);
-            }
-        }
-    }
-
-    private boolean getAirplaneMode() {
-        ContentResolver cr = mContext.getContentResolver();
-        return 0 != Settings.Global.getInt(cr, Settings.Global.AIRPLANE_MODE_ON, 0);
-    }
-
-    // TODO: Fix this racy API by adding something better to TelephonyManager or
-    // ConnectivityService.
-    private void unsafe(final boolean enabled) {
-        AsyncTask.execute(new Runnable() {
-                public void run() {
-                    Settings.Global.putInt(
-                            mContext.getContentResolver(),
-                            Settings.Global.AIRPLANE_MODE_ON,
-                            enabled ? 1 : 0);
-                    Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-                    intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-                    intent.putExtra("state", enabled);
-                    mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
-                }
-            });
-    }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
deleted file mode 100644
index 7939752..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
+++ /dev/null
@@ -1,57 +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.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.ImageView;
-
-public class CompatModeButton extends ImageView {
-    private static final boolean DEBUG = false;
-    private static final String TAG = "StatusBar.CompatModeButton";
-
-    private ActivityManager mAM;
-
-    public CompatModeButton(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public CompatModeButton(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs);
-
-        setClickable(true);
-
-        mAM = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
-
-        refresh();
-    }
-
-    public void refresh() {
-        int mode = mAM.getFrontActivityScreenCompatMode();
-        if (mode == ActivityManager.COMPAT_MODE_UNKNOWN) {
-            // If in an unknown state, don't change.
-            return;
-        }
-        final boolean vis = (mode != ActivityManager.COMPAT_MODE_NEVER
-                          && mode != ActivityManager.COMPAT_MODE_ALWAYS);
-        if (DEBUG) Log.d(TAG, "compat mode is " + mode + "; icon will " + (vis ? "show" : "hide"));
-        setVisibility(vis ? View.VISIBLE : View.GONE);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CurrentUserTracker.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CurrentUserTracker.java
deleted file mode 100644
index 225ebc1..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CurrentUserTracker.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2012 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.systemui.statusbar.policy;
-
-import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-
-public class CurrentUserTracker extends BroadcastReceiver {
-
-    private int mCurrentUserId;
-
-    public CurrentUserTracker(Context context) {
-        IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
-        context.registerReceiver(this, filter);
-        mCurrentUserId = ActivityManager.getCurrentUser();
-    }
-
-    public int getCurrentUserId() {
-        return mCurrentUserId;
-    }
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
-            mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DoNotDisturbController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DoNotDisturbController.java
deleted file mode 100644
index 8612c8f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DoNotDisturbController.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 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.systemui.statusbar.policy;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.widget.CompoundButton;
-
-public class DoNotDisturbController implements CompoundButton.OnCheckedChangeListener,
-        SharedPreferences.OnSharedPreferenceChangeListener {
-    private static final String TAG = "StatusBar.DoNotDisturbController";
-
-    SharedPreferences mPrefs;
-    private Context mContext;
-    private CompoundButton mCheckBox;
-
-    private boolean mDoNotDisturb;
-
-    public DoNotDisturbController(Context context, CompoundButton checkbox) {
-        mContext = context;
-
-        mPrefs = Prefs.read(context);
-        mPrefs.registerOnSharedPreferenceChangeListener(this);
-        mDoNotDisturb = mPrefs.getBoolean(Prefs.DO_NOT_DISTURB_PREF, Prefs.DO_NOT_DISTURB_DEFAULT);
-
-        mCheckBox = checkbox;
-        checkbox.setOnCheckedChangeListener(this);
-
-        checkbox.setChecked(!mDoNotDisturb);
-    }
-
-    // The checkbox is ON for notifications coming in and OFF for Do not disturb, so we
-    // don't have a double negative.
-    public void onCheckedChanged(CompoundButton view, boolean checked) {
-        //Log.d(TAG, "onCheckedChanged checked=" + checked + " mDoNotDisturb=" + mDoNotDisturb);
-        final boolean value = !checked;
-        if (value != mDoNotDisturb) {
-            SharedPreferences.Editor editor = Prefs.edit(mContext);
-            editor.putBoolean(Prefs.DO_NOT_DISTURB_PREF, value);
-            editor.apply();
-        }
-    }
-    
-    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
-        final boolean val = prefs.getBoolean(Prefs.DO_NOT_DISTURB_PREF,
-                Prefs.DO_NOT_DISTURB_DEFAULT);
-        if (val != mDoNotDisturb) {
-            mDoNotDisturb = val;
-            mCheckBox.setChecked(!val);
-        }
-    }
-
-    public void release() {
-        mPrefs.unregisterOnSharedPreferenceChangeListener(this);
-    }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java
deleted file mode 100644
index aca88fe..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EventHole.java
+++ /dev/null
@@ -1,82 +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.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.content.Context;
-import android.graphics.Region;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewTreeObserver;
-
-public class EventHole extends View implements ViewTreeObserver.OnComputeInternalInsetsListener {
-    private static final String TAG = "StatusBar.EventHole";
-
-    private boolean mWindowVis;
-    private int[] mLoc = new int[2];
-
-    public EventHole(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public EventHole(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onWindowVisibilityChanged(int visibility) {
-        super.onWindowVisibilityChanged(visibility);
-        mWindowVis = visibility == View.VISIBLE;
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        getViewTreeObserver().addOnComputeInternalInsetsListener(this);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
-    }
-
-    public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
-        final boolean visible = isShown() && mWindowVis && getWidth() > 0 && getHeight() > 0;
-        final int[] loc = mLoc;
-        getLocationInWindow(loc);
-        final int l = loc[0];
-        final int r = l + getWidth();
-        final int t = loc[1];
-        final int b = t + getHeight();
-        
-        View top = this;
-        while (top.getParent() instanceof View) {
-            top = (View)top.getParent();
-        }
-
-        if (visible) {
-            info.setTouchableInsets(
-                    ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
-            info.touchableRegion.set(0, 0, top.getWidth(), top.getHeight());
-            info.touchableRegion.op(l, t, r, b, Region.Op.DIFFERENCE);
-        } else {
-            info.setTouchableInsets(
-                    ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
-        }
-    }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FixedSizeDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FixedSizeDrawable.java
deleted file mode 100644
index af20411..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FixedSizeDrawable.java
+++ /dev/null
@@ -1,69 +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.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-
-public class FixedSizeDrawable extends Drawable {
-    Drawable mDrawable;
-    int mLeft;
-    int mTop;
-    int mRight;
-    int mBottom;
-
-    public FixedSizeDrawable(Drawable that) {
-        mDrawable = that;
-    }
-
-    public void setFixedBounds(int l, int t, int r, int b) {
-        mLeft = l;
-        mTop = t;
-        mRight = r;
-        mBottom = b;
-    }
-
-    public void setBounds(Rect bounds) {
-        mDrawable.setBounds(mLeft, mTop, mRight, mBottom);
-    }
-
-    public void setBounds(int l, int t, int r, int b) {
-        mDrawable.setBounds(mLeft, mTop, mRight, mBottom);
-    }
-
-    public void draw(Canvas canvas) {
-        mDrawable.draw(canvas);
-    }
-
-    public int getOpacity() {
-        return mDrawable.getOpacity();
-    }
-
-    public void setAlpha(int alpha) {
-        mDrawable.setAlpha(alpha);
-    }
-
-    public int getAlpha() {
-        return mDrawable.getAlpha();
-    }
-
-    public void setColorFilter(ColorFilter cf) {
-        mDrawable.setColorFilter(cf);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
index a759bba..d03f6ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
@@ -22,10 +22,6 @@
 public class Prefs {
     private static final String SHARED_PREFS_NAME = "status_bar";
 
-    // a boolean
-    public static final String DO_NOT_DISTURB_PREF = "do_not_disturb";
-    public static final boolean DO_NOT_DISTURB_DEFAULT = false;
-
     public static final String SHOWN_COMPAT_MODE_HELP = "shown_compat_mode_help";
     public static final String SHOWN_QUICK_SETTINGS_HELP = "shown_quick_settings_help";
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java
deleted file mode 100644
index d3707f2..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/VolumeController.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 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.systemui.statusbar.policy;
-
-import android.content.Context;
-import android.media.AudioManager;
-import android.os.Vibrator;
-
-import com.android.systemui.settings.ToggleSlider;
-
-public class VolumeController implements ToggleSlider.Listener {
-    private static final String TAG = "StatusBar.VolumeController";
-    private static final int STREAM = AudioManager.STREAM_NOTIFICATION;
-
-    private Context mContext;
-    private ToggleSlider mControl;
-    private AudioManager mAudioManager;
-
-    private boolean mMute;
-    private int mVolume;
-    // Is there a vibrator
-    private final boolean mHasVibrator;
-
-    public VolumeController(Context context, ToggleSlider control) {
-        mContext = context;
-        mControl = control;
-
-        Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
-        mHasVibrator = vibrator == null ? false : vibrator.hasVibrator();
-
-        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
-
-        mMute = mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
-        mVolume = mAudioManager.getStreamVolume(STREAM);
-
-        control.setOnChangedListener(this);
-    }
-
-    @Override
-    public void onInit(ToggleSlider control) {
-        control.setMax(mAudioManager.getStreamMaxVolume(STREAM));
-        control.setValue(mVolume);
-        control.setChecked(mMute);
-    }
-
-    public void onChanged(ToggleSlider view, boolean tracking, boolean mute, int level) {
-        if (!tracking) {
-            if (mute) {
-                mAudioManager.setRingerMode(
-                        mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
-                                     : AudioManager.RINGER_MODE_SILENT);
-            } else {
-                mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
-                mAudioManager.setStreamVolume(STREAM, level, AudioManager.FLAG_PLAY_SOUND);
-            }
-        }
-    }
-}
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index ce952d1..6f740cd0 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -43,6 +43,7 @@
 import android.net.RouteInfo;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.INetworkManagementService;
@@ -347,7 +348,7 @@
 
         if (mBandwidthControlEnabled) {
             try {
-                IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"))
+                IBatteryStats.Stub.asInterface(ServiceManager.getService(BatteryStats.SERVICE_NAME))
                         .noteNetworkStatsEnabled();
             } catch (RemoteException e) {
             }
diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java
index 21d3111..9b5f8f6 100644
--- a/services/java/com/android/server/VibratorService.java
+++ b/services/java/com/android/server/VibratorService.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.hardware.input.InputManager;
+import android.os.BatteryStats;
 import android.os.Handler;
 import android.os.IVibratorService;
 import android.os.PowerManager;
@@ -143,7 +144,8 @@
         mWakeLock.setReferenceCounted(true);
 
         mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE));
-        mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
+        mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService(
+                BatteryStats.SERVICE_NAME));
 
         mVibrations = new LinkedList<Vibration>();
 
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 912c465..c558fbd 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -241,11 +241,14 @@
         if (unscheduleServiceRestartLocked(r)) {
             if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
         }
+        r.lastActivity = SystemClock.uptimeMillis();
         r.startRequested = true;
+        if (r.tracker != null) {
+            r.tracker.setStarted(true, mAm.mProcessTracker.getMemFactor(), r.lastActivity);
+        }
         r.callStart = false;
         r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                 service, neededGrants));
-        r.lastActivity = SystemClock.uptimeMillis();
         synchronized (r.stats.getBatteryStats()) {
             r.stats.startRunningLocked();
         }
@@ -261,8 +264,12 @@
             service.stats.stopRunningLocked();
         }
         service.startRequested = false;
+        if (service.tracker != null) {
+            service.tracker.setStarted(false, mAm.mProcessTracker.getMemFactor(),
+                    SystemClock.uptimeMillis());
+        }
         service.callStart = false;
-        bringDownServiceLocked(service, false);
+        bringDownServiceIfNeededLocked(service, false, false);
     }
 
     int stopServiceLocked(IApplicationThread caller, Intent service,
@@ -355,11 +362,15 @@
 
             synchronized (r.stats.getBatteryStats()) {
                 r.stats.stopRunningLocked();
-                r.startRequested = false;
-                r.callStart = false;
             }
+            r.startRequested = false;
+            if (r.tracker != null) {
+                r.tracker.setStarted(false, mAm.mProcessTracker.getMemFactor(),
+                        SystemClock.uptimeMillis());
+            }
+            r.callStart = false;
             final long origId = Binder.clearCallingIdentity();
-            bringDownServiceLocked(r, false);
+            bringDownServiceIfNeededLocked(r, false, false);
             Binder.restoreCallingIdentity(origId);
             return true;
         }
@@ -489,6 +500,17 @@
                         + s);
             }
 
+            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
+                s.lastActivity = SystemClock.uptimeMillis();
+                if (!s.hasAutoCreateConnections()) {
+                    // This is the first binding, let the tracker know.
+                    if (s.tracker != null) {
+                        s.tracker.setBound(true, mAm.mProcessTracker.getMemFactor(),
+                                s.lastActivity);
+                    }
+                }
+            }
+
             AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
             ConnectionRecord c = new ConnectionRecord(b, activity,
                     connection, flags, clientLabel, clientIntent);
@@ -748,7 +770,12 @@
                                 sInfo.applicationInfo.uid, sInfo.packageName,
                                 sInfo.name);
                     }
-                    r = new ServiceRecord(mAm, ss, name, filter, sInfo, res);
+                    ProcessTracker.ServiceState tracker = null;
+                    if ((sInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
+                        tracker = mAm.mProcessTracker.getServiceStateLocked(sInfo.packageName,
+                                sInfo.applicationInfo.uid, sInfo.name);
+                    }
+                    r = new ServiceRecord(mAm, ss, name, filter, sInfo, res, tracker);
                     res.setService(r);
                     mServiceMap.putServiceByName(name, UserHandle.getUserId(r.appInfo.uid), r);
                     mServiceMap.putServiceByIntent(filter, UserHandle.getUserId(r.appInfo.uid), r);
@@ -798,14 +825,19 @@
         else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
                 + why + " of " + r.shortName);
         long now = SystemClock.uptimeMillis();
-        if (r.executeNesting == 0 && r.app != null) {
-            if (r.app.executingServices.size() == 0) {
-                Message msg = mAm.mHandler.obtainMessage(
-                        ActivityManagerService.SERVICE_TIMEOUT_MSG);
-                msg.obj = r.app;
-                mAm.mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
+        if (r.executeNesting == 0) {
+            if (r.tracker != null) {
+                r.tracker.setExecuting(true, mAm.mProcessTracker.getMemFactor(), now);
             }
-            r.app.executingServices.add(r);
+            if (r.app != null) {
+                if (r.app.executingServices.size() == 0) {
+                    Message msg = mAm.mHandler.obtainMessage(
+                            ActivityManagerService.SERVICE_TIMEOUT_MSG);
+                    msg.obj = r.app;
+                    mAm.mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
+                }
+                r.app.executingServices.add(r);
+            }
         }
         r.executeNesting++;
         r.executingStart = now;
@@ -991,7 +1023,7 @@
                     + r.appInfo.uid + " for service "
                     + r.intent.getIntent() + ": user " + r.userId + " is stopped";
             Slog.w(TAG, msg);
-            bringDownServiceLocked(r, true);
+            bringDownServiceLocked(r);
             return msg;
         }
 
@@ -1045,7 +1077,7 @@
                         + r.appInfo.uid + " for service "
                         + r.intent.getIntent() + ": process is bad";
                 Slog.w(TAG, msg);
-                bringDownServiceLocked(r, true);
+                bringDownServiceLocked(r);
                 return msg;
             }
             if (isolated) {
@@ -1167,26 +1199,29 @@
         }
     }
 
-    private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
+    private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
+            boolean hasConn) {
         //Slog.i(TAG, "Bring down service:");
         //r.dump("  ");
 
         // Does it still need to run?
-        if (!force && r.startRequested) {
+        if (r.startRequested) {
             return;
         }
-        if (!force) {
-            // XXX should probably keep a count of the number of auto-create
-            // connections directly in the service.
-            for (int conni=r.connections.size()-1; conni>=0; conni--) {
-                ArrayList<ConnectionRecord> cr = r.connections.valueAt(conni);
-                for (int i=0; i<cr.size(); i++) {
-                    if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
-                        return;
-                    }
-                }
-            }
+
+        if (!knowConn) {
+            hasConn = r.hasAutoCreateConnections();
         }
+        if (hasConn) {
+            return;
+        }
+
+        bringDownServiceLocked(r);
+    }
+
+    private final void bringDownServiceLocked(ServiceRecord r) {
+        //Slog.i(TAG, "Bring down service:");
+        //r.dump("  ");
 
         // Report to all of the connections that the service is no longer
         // available.
@@ -1291,6 +1326,13 @@
         if (r.restarter instanceof ServiceRestarter) {
            ((ServiceRestarter)r.restarter).setService(null);
         }
+
+        int memFactor = mAm.mProcessTracker.getMemFactor();
+        long now = SystemClock.uptimeMillis();
+        if (r.tracker != null) {
+            r.tracker.setStarted(false, memFactor, now);
+            r.tracker.setBound(false, memFactor, now);
+        }
     }
 
     void removeConnectionLocked(
@@ -1349,7 +1391,14 @@
             }
 
             if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
-                bringDownServiceLocked(s, false);
+                boolean hasAutoCreate = s.hasAutoCreateConnections();
+                if (!hasAutoCreate) {
+                    if (s.tracker != null) {
+                        s.tracker.setBound(false, mAm.mProcessTracker.getMemFactor(),
+                                SystemClock.uptimeMillis());
+                    }
+                }
+                bringDownServiceIfNeededLocked(s, true, hasAutoCreate);
             }
         }
     }
@@ -1422,22 +1471,28 @@
                 + ", inStopping=" + inStopping + ", app=" + r.app);
         else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
         r.executeNesting--;
-        if (r.executeNesting <= 0 && r.app != null) {
-            if (DEBUG_SERVICE) Slog.v(TAG,
-                    "Nesting at 0 of " + r.shortName);
-            r.app.executingServices.remove(r);
-            if (r.app.executingServices.size() == 0) {
-                if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
-                        "No more executingServices of " + r.shortName);
-                mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
-            }
-            if (inStopping) {
+        if (r.executeNesting <= 0) {
+            if (r.app != null) {
                 if (DEBUG_SERVICE) Slog.v(TAG,
-                        "doneExecuting remove stopping " + r);
-                mStoppingServices.remove(r);
-                r.bindings.clear();
+                        "Nesting at 0 of " + r.shortName);
+                r.app.executingServices.remove(r);
+                if (r.app.executingServices.size() == 0) {
+                    if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
+                            "No more executingServices of " + r.shortName);
+                    mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
+                }
+                if (inStopping) {
+                    if (DEBUG_SERVICE) Slog.v(TAG,
+                            "doneExecuting remove stopping " + r);
+                    mStoppingServices.remove(r);
+                    r.bindings.clear();
+                }
+                mAm.updateOomAdjLocked(r.app);
             }
-            mAm.updateOomAdjLocked(r.app);
+            if (r.tracker != null) {
+                r.tracker.setExecuting(false, mAm.mProcessTracker.getMemFactor(),
+                        SystemClock.uptimeMillis());
+            }
         }
     }
 
@@ -1494,7 +1549,7 @@
                 sr.isolatedProc = null;
                 mPendingServices.remove(i);
                 i--;
-                bringDownServiceLocked(sr, true);
+                bringDownServiceLocked(sr);
             }
         }
     }
@@ -1545,7 +1600,7 @@
 
         int N = services.size();
         for (int i=0; i<N; i++) {
-            bringDownServiceLocked(services.get(i), true);
+            bringDownServiceLocked(services.get(i));
         }
         return didSomething;
     }
@@ -1628,6 +1683,10 @@
                 sr.app = null;
                 sr.isolatedProc = null;
                 sr.executeNesting = 0;
+                if (sr.tracker != null) {
+                    sr.tracker.setExecuting(false, mAm.mProcessTracker.getMemFactor(),
+                            SystemClock.uptimeMillis());
+                }
                 if (mStoppingServices.remove(sr)) {
                     if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
                 }
@@ -1647,9 +1706,9 @@
                             + " times, stopping: " + sr);
                     EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
                             sr.userId, sr.crashCount, sr.shortName, app.pid);
-                    bringDownServiceLocked(sr, true);
+                    bringDownServiceLocked(sr);
                 } else if (!allowRestart) {
-                    bringDownServiceLocked(sr, true);
+                    bringDownServiceLocked(sr);
                 } else {
                     boolean canceled = scheduleServiceRestartLocked(sr, true);
 
@@ -1659,9 +1718,13 @@
                     if (sr.startRequested && (sr.stopIfKilled || canceled)) {
                         if (sr.pendingStarts.size() == 0) {
                             sr.startRequested = false;
-                            if (numClients > 0) {
+                            if (sr.tracker != null) {
+                                sr.tracker.setStarted(false, mAm.mProcessTracker.getMemFactor(),
+                                        SystemClock.uptimeMillis());
+                            }
+                            if (!sr.hasAutoCreateConnections()) {
                                 // Whoops, no reason to restart!
-                                bringDownServiceLocked(sr, true);
+                                bringDownServiceLocked(sr);
                             }
                         }
                     }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 2124095..21c752b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7292,7 +7292,6 @@
         if (isolated) {
             int userId = UserHandle.getUserId(uid);
             int stepsLeft = Process.LAST_ISOLATED_UID - Process.FIRST_ISOLATED_UID + 1;
-            uid = 0;
             while (true) {
                 if (mNextIsolatedProcessUid < Process.FIRST_ISOLATED_UID
                         || mNextIsolatedProcessUid > Process.LAST_ISOLATED_UID) {
@@ -7314,7 +7313,7 @@
             ps = stats.getProcessStatsLocked(info.uid, proc);
         }
         return new ProcessRecord(ps, thread, info, proc, uid,
-                mProcessTracker.getProcessStateLocked(info.packageName, uid, proc));
+                mProcessTracker.getProcessStateLocked(info.packageName, info.uid, proc));
     }
 
     final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) {
@@ -14193,7 +14192,7 @@
         // are managing to keep around is less than half the maximum we desire;
         // if we are keeping a good number around, we'll let them use whatever
         // memory they want.
-        int memFactor = ProcessTracker.STATE_MEM_FACTOR_NORMAL_ADJ;
+        int memFactor = ProcessTracker.ADJ_MEM_FACTOR_NORMAL;
         if (numCached <= ProcessList.TRIM_CACHED_APPS
                 && numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
             final int numCachedAndEmpty = numCached + numEmpty;
@@ -14207,13 +14206,13 @@
             int fgTrimLevel;
             if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
-                memFactor = ProcessTracker.STATE_MEM_FACTOR_CRITIAL_ADJ;
+                memFactor = ProcessTracker.ADJ_MEM_FACTOR_CRITICAL;
             } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
-                memFactor = ProcessTracker.STATE_MEM_FACTOR_LOW_ADJ;
+                memFactor = ProcessTracker.ADJ_MEM_FACTOR_LOW;
             } else {
                 fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
-                memFactor = ProcessTracker.STATE_MEM_FACTOR_MODERATE_ADJ;
+                memFactor = ProcessTracker.ADJ_MEM_FACTOR_MODERATE;
             }
             int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
             for (i=0; i<N; i++) {
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index f143feb..12cad7b 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -59,7 +60,7 @@
     
     public void publish(Context context) {
         mContext = context;
-        ServiceManager.addService("batteryinfo", asBinder());
+        ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
         mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps());
         mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_radioScanningTimeout)
@@ -77,7 +78,7 @@
         if (sService != null) {
             return sService;
         }
-        IBinder b = ServiceManager.getService("batteryinfo");
+        IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME);
         sService = asInterface(b);
         return sService;
     }
@@ -479,7 +480,7 @@
     }
     
     private void dumpHelp(PrintWriter pw) {
-        pw.println("Battery stats (batteryinfo) dump options:");
+        pw.println("Battery stats (batterystats) dump options:");
         pw.println("  [--checkin] [--unplugged] [--reset] [--write] [-h] [<package.name>]");
         pw.println("  --checkin: format output for a checkin report.");
         pw.println("  --unplugged: only output data since last unplugged.");
diff --git a/services/java/com/android/server/am/ProcessTracker.java b/services/java/com/android/server/am/ProcessTracker.java
index fb8d09c..ec8a0b2 100644
--- a/services/java/com/android/server/am/ProcessTracker.java
+++ b/services/java/com/android/server/am/ProcessTracker.java
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -24,6 +25,9 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 
 public final class ProcessTracker {
     public static final int STATE_NOTHING = -1;
@@ -36,16 +40,18 @@
     public static final int STATE_HOME = 6;
     public static final int STATE_PREVIOUS = 7;
     public static final int STATE_CACHED = 8;
-    public static final int STATE_MEM_FACTOR_MOD = STATE_CACHED+1;
-    public static final int STATE_MEM_FACTOR_NORMAL_ADJ = 0;
-    public static final int STATE_MEM_FACTOR_MODERATE_ADJ = STATE_MEM_FACTOR_MOD;
-    public static final int STATE_MEM_FACTOR_LOW_ADJ = STATE_MEM_FACTOR_MOD*2;
-    public static final int STATE_MEM_FACTOR_CRITIAL_ADJ = STATE_MEM_FACTOR_MOD*3;
-    public static final int STATE_MEM_FACTOR_COUNT = STATE_MEM_FACTOR_MOD*4;
-    public static final int STATE_SCREEN_ON_MOD = STATE_MEM_FACTOR_COUNT;
-    public static final int STATE_SCREEN_OFF_ADJ = 0;
-    public static final int STATE_SCREEN_ON_ADJ = STATE_SCREEN_ON_MOD;
-    public static final int STATE_COUNT = STATE_SCREEN_ON_MOD*2;
+    public static final int STATE_COUNT = STATE_CACHED+1;
+
+    public static final int ADJ_NOTHING = -1;
+    public static final int ADJ_MEM_FACTOR_NORMAL = 0;
+    public static final int ADJ_MEM_FACTOR_MODERATE = 1;
+    public static final int ADJ_MEM_FACTOR_LOW = 2;
+    public static final int ADJ_MEM_FACTOR_CRITICAL = 3;
+    public static final int ADJ_MEM_FACTOR_COUNT = ADJ_MEM_FACTOR_CRITICAL+1;
+    public static final int ADJ_SCREEN_MOD = ADJ_MEM_FACTOR_COUNT;
+    public static final int ADJ_SCREEN_OFF = 0;
+    public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD;
+    public static final int ADJ_COUNT = ADJ_SCREEN_ON*2;
 
     static String[] STATE_NAMES = new String[] {
             "Top        ", "Foreground ", "Visible    ", "Perceptible", "Backup     ",
@@ -53,13 +59,25 @@
     };
 
     public static final class ProcessState {
-        final long[] mDurations = new long[STATE_COUNT];
+        final String mPackage;
+        final int mUid;
+        final String mName;
+
+        final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
         int mCurState = STATE_NOTHING;
         long mStartTime;
 
+        long mTmpTotalTime;
+
+        public ProcessState(String pkg, int uid, String name) {
+            mPackage = pkg;
+            mUid = uid;
+            mName = name;
+        }
+
         public void setState(int state, int memFactor, long now) {
             if (state != STATE_NOTHING) {
-                state += memFactor;
+                state += memFactor*STATE_COUNT;
             }
             if (mCurState != state) {
                 if (mCurState != STATE_NOTHING) {
@@ -72,8 +90,59 @@
     }
 
     public static final class ServiceState {
-        long mStartedDuration;
-        long mStartedTime;
+        final long[] mStartedDurations = new long[ADJ_COUNT];
+        int mStartedCount;
+        int mStartedState = STATE_NOTHING;
+        long mStartedStartTime;
+
+        final long[] mBoundDurations = new long[ADJ_COUNT];
+        int mBoundCount;
+        int mBoundState = STATE_NOTHING;
+        long mBoundStartTime;
+
+        final long[] mExecDurations = new long[ADJ_COUNT];
+        int mExecCount;
+        int mExecState = STATE_NOTHING;
+        long mExecStartTime;
+
+        public void setStarted(boolean started, int memFactor, long now) {
+            int state = started ? memFactor : STATE_NOTHING;
+            if (mStartedState != state) {
+                if (mStartedState != STATE_NOTHING) {
+                    mStartedDurations[mStartedState] += now - mStartedStartTime;
+                } else if (started) {
+                    mStartedCount++;
+                }
+                mStartedState = state;
+                mStartedStartTime = now;
+            }
+        }
+
+        public void setBound(boolean bound, int memFactor, long now) {
+            int state = bound ? memFactor : STATE_NOTHING;
+            if (mBoundState != state) {
+                if (mBoundState != STATE_NOTHING) {
+                    mBoundDurations[mBoundState] += now - mBoundStartTime;
+                } else if (bound) {
+                    mBoundCount++;
+                }
+                mBoundState = state;
+                mBoundStartTime = now;
+            }
+        }
+
+        public void setExecuting(boolean executing, int memFactor, long now) {
+            int state = executing ? memFactor : STATE_NOTHING;
+            if (mExecState != state) {
+                if (mExecState != STATE_NOTHING) {
+                    mExecDurations[mExecState] += now - mExecStartTime;
+                } else if (executing) {
+                    mExecCount++;
+                }
+                mExecState = state;
+                mExecStartTime = now;
+            }
+        }
     }
 
     public static final class PackageState {
@@ -88,7 +157,7 @@
 
     static final class State {
         final ProcessMap<PackageState> mPackages = new ProcessMap<PackageState>();
-        final long[] mMemFactorDurations = new long[STATE_COUNT/STATE_MEM_FACTOR_MOD];
+        final long[] mMemFactorDurations = new long[ADJ_COUNT];
         int mMemFactor = STATE_NOTHING;
         long mStartTime;
     }
@@ -114,7 +183,7 @@
         if (ps != null) {
             return ps;
         }
-        ps = new ProcessState();
+        ps = new ProcessState(packageName, uid, processName);
         as.mProcesses.put(processName, ps);
         return ps;
     }
@@ -132,15 +201,31 @@
 
     public boolean setMemFactor(int memFactor, boolean screenOn, long now) {
         if (screenOn) {
-            memFactor += STATE_SCREEN_ON_MOD;
+            memFactor += ADJ_SCREEN_ON;
         }
         if (memFactor != mState.mMemFactor) {
             if (mState.mMemFactor != STATE_NOTHING) {
-                mState.mMemFactorDurations[mState.mMemFactor/STATE_MEM_FACTOR_MOD]
-                        += now - mState.mStartTime;
+                mState.mMemFactorDurations[mState.mMemFactor] += now - mState.mStartTime;
             }
             mState.mMemFactor = memFactor;
             mState.mStartTime = now;
+            ArrayMap<String, SparseArray<PackageState>> pmap = mState.mPackages.getMap();
+            for (int i=0; i<pmap.size(); i++) {
+                SparseArray<PackageState> uids = pmap.valueAt(i);
+                for (int j=0; j<uids.size(); j++) {
+                    PackageState pkg = uids.valueAt(j);
+                    ArrayMap<String, ServiceState> services = pkg.mServices;
+                    for (int k=0; k<services.size(); k++) {
+                        ServiceState service = services.valueAt(k);
+                        if (service.mStartedState != STATE_NOTHING) {
+                            service.setStarted(true, memFactor, now);
+                        }
+                        if (service.mBoundState != STATE_NOTHING) {
+                            service.setBound(true, memFactor, now);
+                        }
+                    }
+                }
+            }
             return true;
         }
         return false;
@@ -150,15 +235,15 @@
         return mState.mMemFactor != STATE_NOTHING ? mState.mMemFactor : 0;
     }
 
-    private void printScreenLabel(PrintWriter pw, int offset) {
+    static private void printScreenLabel(PrintWriter pw, int offset) {
         switch (offset) {
-            case STATE_NOTHING:
+            case ADJ_NOTHING:
                 pw.print("             ");
                 break;
-            case STATE_SCREEN_OFF_ADJ:
+            case ADJ_SCREEN_OFF:
                 pw.print("Screen Off / ");
                 break;
-            case STATE_SCREEN_ON_ADJ:
+            case ADJ_SCREEN_ON:
                 pw.print("Screen On  / ");
                 break;
             default:
@@ -167,21 +252,21 @@
         }
     }
 
-    private void printMemLabel(PrintWriter pw, int offset) {
+    static private void printMemLabel(PrintWriter pw, int offset) {
         switch (offset) {
-            case STATE_NOTHING:
+            case ADJ_NOTHING:
                 pw.print("       ");
                 break;
-            case STATE_MEM_FACTOR_NORMAL_ADJ:
+            case ADJ_MEM_FACTOR_NORMAL:
                 pw.print("Norm / ");
                 break;
-            case STATE_MEM_FACTOR_MODERATE_ADJ:
+            case ADJ_MEM_FACTOR_MODERATE:
                 pw.print("Mod  / ");
                 break;
-            case STATE_MEM_FACTOR_LOW_ADJ:
+            case ADJ_MEM_FACTOR_LOW:
                 pw.print("Low  / ");
                 break;
-            case STATE_MEM_FACTOR_CRITIAL_ADJ:
+            case ADJ_MEM_FACTOR_CRITICAL:
                 pw.print("Crit / ");
                 break;
             default:
@@ -190,29 +275,191 @@
         }
     }
 
+    static void dumpSingleTime(PrintWriter pw, String prefix, long[] durations,
+            int curState, long curStartTime, long now) {
+        long totalTime = 0;
+        int printedScreen = -1;
+        for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
+            int printedMem = -1;
+            for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
+                int state = imem+iscreen;
+                long time = durations[state];
+                String running = "";
+                if (curState == state) {
+                    time += now - curStartTime;
+                    running = " (running)";
+                }
+                if (time != 0) {
+                    pw.print(prefix);
+                    printScreenLabel(pw, printedScreen != iscreen
+                            ? iscreen : STATE_NOTHING);
+                    printedScreen = iscreen;
+                    printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+                    printedMem = imem;
+                    TimeUtils.formatDuration(time, pw); pw.println(running);
+                    totalTime += time;
+                }
+            }
+        }
+        if (totalTime != 0) {
+            pw.print(prefix);
+            printScreenLabel(pw, STATE_NOTHING);
+            pw.print("TOTAL: ");
+            TimeUtils.formatDuration(totalTime, pw);
+            pw.println();
+        }
+    }
+
+    long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates,
+                int[] procStates, long now) {
+        long totalTime = 0;
+        for (int is=0; is<screenStates.length; is++) {
+            for (int im=0; im<memStates.length; im++) {
+                for (int ip=0; ip<procStates.length; ip++) {
+                    int bucket = ((screenStates[is]+ memStates[im]) * STATE_COUNT)
+                            + procStates[ip];
+                    totalTime += proc.mDurations[bucket];
+                    if (proc.mCurState == bucket) {
+                        totalTime += now - proc.mStartTime;
+                    }
+                }
+            }
+        }
+        proc.mTmpTotalTime = totalTime;
+        return totalTime;
+    }
+
+    ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
+            int[] procStates, long now) {
+        ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>();
+        ArrayMap<String, SparseArray<PackageState>> pmap = mState.mPackages.getMap();
+        for (int ip=0; ip<pmap.size(); ip++) {
+            SparseArray<PackageState> procs = pmap.valueAt(ip);
+            for (int iu=0; iu<procs.size(); iu++) {
+                PackageState state = procs.valueAt(iu);
+                for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {
+                    if (computeProcessTimeLocked(state.mProcesses.valueAt(iproc),
+                            screenStates, memStates, procStates, now) > 0) {
+                        outProcs.add(state.mProcesses.valueAt(iproc));
+                    }
+                }
+            }
+        }
+        Collections.sort(outProcs, new Comparator<ProcessState>() {
+            @Override
+            public int compare(ProcessState lhs, ProcessState rhs) {
+                if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) {
+                    return -1;
+                } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) {
+                    return 1;
+                }
+                return 0;
+            }
+        });
+        return outProcs;
+    }
+
+    void dumpProcessState(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates,
+            int[] memStates, int[] procStates, long now) {
+        long totalTime = 0;
+        int printedScreen = -1;
+        for (int is=0; is<screenStates.length; is++) {
+            int printedMem = -1;
+            for (int im=0; im<memStates.length; im++) {
+                for (int ip=0; ip<procStates.length; ip++) {
+                    final int iscreen = screenStates[is];
+                    final int imem = memStates[im];
+                    final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
+                    long time = proc.mDurations[bucket];
+                    String running = "";
+                    if (proc.mCurState == bucket) {
+                        time += now - proc.mStartTime;
+                        running = " (running)";
+                    }
+                    totalTime += time;
+                    if (time != 0) {
+                        pw.print(prefix);
+                        if (screenStates.length > 1) {
+                            printScreenLabel(pw, printedScreen != iscreen
+                                    ? iscreen : STATE_NOTHING);
+                            printedScreen = iscreen;
+                        }
+                        if (memStates.length > 1) {
+                            printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+                            printedMem = imem;
+                        }
+                        pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
+                        TimeUtils.formatDuration(time, pw); pw.println(running);
+                        totalTime += time;
+                    }
+                }
+            }
+        }
+        if (totalTime != 0) {
+            pw.print(prefix);
+            if (screenStates.length > 1) {
+                printScreenLabel(pw, STATE_NOTHING);
+            }
+            if (memStates.length > 1) {
+                printMemLabel(pw, STATE_NOTHING);
+            }
+            pw.print("TOTAL      : ");
+            TimeUtils.formatDuration(totalTime, pw);
+            pw.println();
+        }
+    }
+
+    void dumpProcessList(PrintWriter pw, String prefix, ArrayList<ProcessState> procs,
+            int[] screenStates, int[] memStates, int[] procStates, long now) {
+        String innerPrefix = prefix + "  ";
+        for (int i=procs.size()-1; i>=0; i--) {
+            ProcessState proc = procs.get(i);
+            pw.print(prefix);
+            pw.print(proc.mPackage);
+            pw.print(" / ");
+            UserHandle.formatUid(pw, proc.mUid);
+            pw.print(" / ");
+            pw.print(proc.mName);
+            pw.println(":");
+            dumpProcessState(pw, innerPrefix, proc, screenStates, memStates, procStates, now);
+        }
+    }
+
+    void dumpFilteredProcesses(PrintWriter pw, String header, String prefix,
+            int[] screenStates, int[] memStates, int[] procStates, long now) {
+        ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
+                procStates, now);
+        if (procs.size() > 0) {
+            pw.println();
+            pw.println(header);
+            dumpProcessList(pw, prefix, procs, screenStates, memStates, procStates, now);
+        }
+    }
+
     public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
         final long now = SystemClock.uptimeMillis();
         ArrayMap<String, SparseArray<PackageState>> pmap = mState.mPackages.getMap();
-        pw.println("Process Stats:");
+        pw.println("Per-Package Process Stats:");
         for (int ip=0; ip<pmap.size(); ip++) {
             String procName = pmap.keyAt(ip);
             SparseArray<PackageState> procs = pmap.valueAt(ip);
             for (int iu=0; iu<procs.size(); iu++) {
                 int uid = procs.keyAt(iu);
                 PackageState state = procs.valueAt(iu);
-                pw.print("  "); pw.print(procName); pw.print(" / "); pw.print(uid); pw.println(":");
+                pw.print("  * "); pw.print(procName); pw.print(" / ");
+                        UserHandle.formatUid(pw, uid); pw.println(":");
                 for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {
-                    pw.print("    Process ");
+                    pw.print("      Process ");
                     pw.print(state.mProcesses.keyAt(iproc));
                     pw.println(":");
                     long totalTime = 0;
                     ProcessState proc = state.mProcesses.valueAt(iproc);
                     int printedScreen = -1;
-                    for (int iscreen=0; iscreen<STATE_COUNT; iscreen+=STATE_SCREEN_ON_MOD) {
+                    for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
                         int printedMem = -1;
-                        for (int imem=0; imem<STATE_MEM_FACTOR_COUNT; imem+=STATE_MEM_FACTOR_MOD) {
+                        for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
                             for (int is=0; is<STATE_NAMES.length; is++) {
-                                int bucket = is+imem+iscreen;
+                                int bucket = is+(STATE_COUNT*(imem+iscreen));
                                 long time = proc.mDurations[bucket];
                                 String running = "";
                                 if (proc.mCurState == bucket) {
@@ -220,7 +467,7 @@
                                     running = " (running)";
                                 }
                                 if (time != 0) {
-                                    pw.print("      ");
+                                    pw.print("        ");
                                     printScreenLabel(pw, printedScreen != iscreen
                                             ? iscreen : STATE_NOTHING);
                                     printedScreen = iscreen;
@@ -234,7 +481,7 @@
                         }
                     }
                     if (totalTime != 0) {
-                        pw.print("      ");
+                        pw.print("        ");
                         printScreenLabel(pw, STATE_NOTHING);
                         printMemLabel(pw, STATE_NOTHING);
                         pw.print("TOTAL      : ");
@@ -243,53 +490,46 @@
                     }
                 }
                 for (int isvc=0; isvc<state.mServices.size(); isvc++) {
-                    pw.print("    Service ");
+                    pw.print("      Service ");
                     pw.print(state.mServices.keyAt(isvc));
                     pw.println(":");
                     ServiceState svc = state.mServices.valueAt(isvc);
-                    long time = svc.mStartedDuration;
-                    if (svc.mStartedTime >= 0) {
-                        time += now - svc.mStartedTime;
+                    if (svc.mStartedCount != 0) {
+                        pw.print("        Started op count "); pw.print(svc.mStartedCount);
+                        pw.println(":");
+                        dumpSingleTime(pw, "          ", svc.mStartedDurations, svc.mStartedState,
+                                svc.mStartedStartTime, now);
                     }
-                    if (time != 0) {
-                        pw.print("    Started: ");
-                        TimeUtils.formatDuration(time, pw); pw.println();
+                    if (svc.mBoundCount != 0) {
+                        pw.print("        Bound op count "); pw.print(svc.mBoundCount);
+                        pw.println(":");
+                        dumpSingleTime(pw, "          ", svc.mBoundDurations, svc.mBoundState,
+                                svc.mBoundStartTime, now);
+                    }
+                    if (svc.mExecCount != 0) {
+                        pw.print("        Executing op count "); pw.print(svc.mExecCount);
+                        pw.println(":");
+                        dumpSingleTime(pw, "          ", svc.mExecDurations, svc.mExecState,
+                                svc.mExecStartTime, now);
                     }
                 }
             }
         }
+        dumpFilteredProcesses(pw, "Processes running while critical mem:", "  ",
+                new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
+                new int[] {ADJ_MEM_FACTOR_CRITICAL},
+                new int[] {STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE, STATE_PERCEPTIBLE,
+                        STATE_BACKUP, STATE_SERVICE, STATE_HOME, STATE_PREVIOUS},
+                now);
+        dumpFilteredProcesses(pw, "Processes running while low mem:", "  ",
+                new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
+                new int[] {ADJ_MEM_FACTOR_LOW},
+                new int[] {STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE, STATE_PERCEPTIBLE,
+                        STATE_BACKUP, STATE_SERVICE, STATE_HOME, STATE_PREVIOUS},
+                now);
         pw.println();
         pw.println("Run time Stats:");
-        long totalTime = 0;
-        int printedScreen = -1;
-        for (int iscreen=0; iscreen<STATE_COUNT; iscreen+=STATE_SCREEN_ON_MOD) {
-            int printedMem = -1;
-            for (int imem=0; imem<STATE_MEM_FACTOR_COUNT; imem+=STATE_MEM_FACTOR_MOD) {
-                int bucket = imem+iscreen;
-                long time = mState.mMemFactorDurations[bucket/STATE_MEM_FACTOR_MOD];
-                String running = "";
-                if (mState.mMemFactor == bucket) {
-                    time += now - mState.mStartTime;
-                    running = " (running)";
-                }
-                if (time != 0) {
-                    pw.print("  ");
-                    printScreenLabel(pw, printedScreen != iscreen
-                            ? iscreen : STATE_NOTHING);
-                    printedScreen = iscreen;
-                    printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
-                    printedMem = imem;
-                    TimeUtils.formatDuration(time, pw); pw.println(running);
-                    totalTime += time;
-                }
-            }
-        }
-        if (totalTime != 0) {
-            pw.print("  ");
-            printScreenLabel(pw, STATE_NOTHING);
-            pw.print("TOTAL: ");
-            TimeUtils.formatDuration(totalTime, pw);
-            pw.println();
-        }
+        dumpSingleTime(pw, "  ", mState.mMemFactorDurations, mState.mMemFactor,
+                mState.mStartTime, now);
     }
 }
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 45e248b..5000940 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -73,6 +73,7 @@
     final String dataDir;   // where activity data should go
     final boolean exported; // from ServiceInfo.exported
     final Runnable restarter; // used to schedule retries of starting the service
+    final ProcessTracker.ServiceState tracker; // tracking service execution, may be null
     final long createTime;  // when this service was created
     final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
             = new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
@@ -281,7 +282,8 @@
 
     ServiceRecord(ActivityManagerService ams,
             BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name,
-            Intent.FilterComparison intent, ServiceInfo sInfo, Runnable restarter) {
+            Intent.FilterComparison intent, ServiceInfo sInfo, Runnable restarter,
+            ProcessTracker.ServiceState tracker) {
         this.ams = ams;
         this.stats = servStats;
         this.name = name;
@@ -297,6 +299,7 @@
         dataDir = sInfo.applicationInfo.dataDir;
         exported = sInfo.exported;
         this.restarter = restarter;
+        this.tracker = tracker;
         createTime = SystemClock.elapsedRealtime();
         lastActivity = SystemClock.uptimeMillis();
         userId = UserHandle.getUserId(appInfo.uid);
@@ -319,6 +322,20 @@
         return a;
     }
 
+    public boolean hasAutoCreateConnections() {
+        // XXX should probably keep a count of the number of auto-create
+        // connections directly in the service.
+        for (int conni=connections.size()-1; conni>=0; conni--) {
+            ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
+            for (int i=0; i<cr.size(); i++) {
+                if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     public void resetRestartCounter() {
         restartCount = 0;
         restartDelay = 0;
diff --git a/services/java/com/android/server/display/PersistentDataStore.java b/services/java/com/android/server/display/PersistentDataStore.java
index d5d7132..67b3695 100644
--- a/services/java/com/android/server/display/PersistentDataStore.java
+++ b/services/java/com/android/server/display/PersistentDataStore.java
@@ -106,7 +106,7 @@
             }
             if (!Objects.equal(display.getDeviceAlias(), alias)) {
                 return new WifiDisplay(display.getDeviceAddress(), display.getDeviceName(),
-                        alias, display.canConnect());
+                        alias, display.isAvailable(), display.canConnect(), display.isRemembered());
             }
         }
         return display;
@@ -260,7 +260,8 @@
                 }
 
                 mRememberedWifiDisplays.add(
-                        new WifiDisplay(deviceAddress, deviceName, deviceAlias));
+                        new WifiDisplay(deviceAddress, deviceName, deviceAlias,
+                                false, false, false));
             }
         }
     }
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java
index b655b3a..4c80cf5 100644
--- a/services/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -45,6 +45,8 @@
 
 import java.io.PrintWriter;
 import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
 
 import libcore.util.Objects;
 
@@ -88,6 +90,7 @@
     private int mScanState;
     private int mActiveDisplayState;
     private WifiDisplay mActiveDisplay;
+    private WifiDisplay[] mDisplays = WifiDisplay.EMPTY_ARRAY;
     private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY;
     private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY;
 
@@ -116,6 +119,7 @@
         pw.println("mScanState=" + mScanState);
         pw.println("mActiveDisplayState=" + mActiveDisplayState);
         pw.println("mActiveDisplay=" + mActiveDisplay);
+        pw.println("mDisplays=" + Arrays.toString(mDisplays));
         pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
         pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
         pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
@@ -229,7 +233,8 @@
 
         WifiDisplay display = mPersistentDataStore.getRememberedWifiDisplay(address);
         if (display != null && !Objects.equal(display.getDeviceAlias(), alias)) {
-            display = new WifiDisplay(address, display.getDeviceName(), alias);
+            display = new WifiDisplay(address, display.getDeviceName(), alias,
+                    false, false, false);
             if (mPersistentDataStore.rememberWifiDisplay(display)) {
                 mPersistentDataStore.saveIfNeeded();
                 updateRememberedDisplaysLocked();
@@ -262,7 +267,7 @@
         if (mCurrentStatus == null) {
             mCurrentStatus = new WifiDisplayStatus(
                     mFeatureState, mScanState, mActiveDisplayState,
-                    mActiveDisplay, mAvailableDisplays, mRememberedDisplays);
+                    mActiveDisplay, mDisplays);
         }
 
         if (DEBUG) {
@@ -271,10 +276,36 @@
         return mCurrentStatus;
     }
 
+    private void updateDisplaysLocked() {
+        List<WifiDisplay> displays = new ArrayList<WifiDisplay>(
+                mAvailableDisplays.length + mRememberedDisplays.length);
+        boolean[] remembered = new boolean[mAvailableDisplays.length];
+        for (WifiDisplay d : mRememberedDisplays) {
+            boolean available = false;
+            for (int i = 0; i < mAvailableDisplays.length; i++) {
+                if (d.equals(mAvailableDisplays[i])) {
+                    remembered[i] = available = true;
+                    break;
+                }
+            }
+            if (!available) {
+                displays.add(new WifiDisplay(d.getDeviceAddress(), d.getDeviceName(),
+                        d.getDeviceAlias(), false, false, true));
+            }
+        }
+        for (int i = 0; i < mAvailableDisplays.length; i++) {
+            WifiDisplay d = mAvailableDisplays[i];
+            displays.add(new WifiDisplay(d.getDeviceAddress(), d.getDeviceName(),
+                    d.getDeviceAlias(), true, d.canConnect(), remembered[i]));
+        }
+        mDisplays = displays.toArray(WifiDisplay.EMPTY_ARRAY);
+    }
+
     private void updateRememberedDisplaysLocked() {
         mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays();
         mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay);
         mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays);
+        updateDisplaysLocked();
     }
 
     private void fixRememberedDisplayNamesFromAvailableDisplaysLocked() {
@@ -487,11 +518,18 @@
                 availableDisplays = mPersistentDataStore.applyWifiDisplayAliases(
                         availableDisplays);
 
-                if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING
-                        || !Arrays.equals(mAvailableDisplays, availableDisplays)) {
+                // check if any of the available displays changed canConnect status
+                boolean changed = !Arrays.equals(mAvailableDisplays, availableDisplays);
+                for (int i = 0; !changed && i<availableDisplays.length; i++) {
+                    changed = availableDisplays[i].canConnect()
+                            != mAvailableDisplays[i].canConnect();
+                }
+
+                if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING || changed) {
                     mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING;
                     mAvailableDisplays = availableDisplays;
                     fixRememberedDisplayNamesFromAvailableDisplaysLocked();
+                    updateDisplaysLocked();
                     scheduleStatusChangedBroadcastLocked();
                 }
             }
diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java
index e595df4..f89917c3 100644
--- a/services/java/com/android/server/display/WifiDisplayController.java
+++ b/services/java/com/android/server/display/WifiDisplayController.java
@@ -898,7 +898,7 @@
 
     private static WifiDisplay createWifiDisplay(WifiP2pDevice device) {
         return new WifiDisplay(device.deviceAddress, device.deviceName, null,
-                device.wfdInfo.isSessionAvailable());
+                true, device.wfdInfo.isSessionAvailable(), false);
     }
 
     private final BroadcastReceiver mWifiP2pReceiver = new BroadcastReceiver() {
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 8c88cab..4791ec0 100644
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -41,6 +41,7 @@
 import android.net.NetworkInfo;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -456,7 +457,8 @@
                 Context.APP_OPS_SERVICE));
 
         // Battery statistics service to be notified when GPS turns on or off
-        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
+        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
+                BatteryStats.SERVICE_NAME));
 
         mProperties = new Properties();
         try {
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 9f3a0d3..1040ab19 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -54,6 +54,7 @@
 import android.net.wifi.WpsResult.Status;
 import android.net.wifi.p2p.WifiP2pManager;
 import android.net.wifi.p2p.WifiP2pService;
+import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
@@ -542,7 +543,8 @@
         mInterfaceName = wlanInterface;
 
         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
-        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
+        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
+                BatteryStats.SERVICE_NAME));
 
         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
         mNwService = INetworkManagementService.Stub.asInterface(b);