Merge "Create ListPopupWindow handler against main looper" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 7891c71..a0dccd5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15863,6 +15863,10 @@
     ctor public MediaDrmException(java.lang.String);
   }
 
+  public class MediaDrmResetException extends java.lang.IllegalStateException {
+    ctor public MediaDrmResetException(java.lang.String);
+  }
+
   public final class MediaExtractor {
     ctor public MediaExtractor();
     method public boolean advance();
@@ -30620,6 +30624,7 @@
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
+    field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
     field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
     field public static final java.lang.String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
     field public static final java.lang.String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
@@ -30677,6 +30682,9 @@
     field public static final java.lang.String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
     field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
     field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
+    field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
+    field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
+    field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
     field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
 
@@ -31240,6 +31248,8 @@
     field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3
     field public static final int SIM_STATE_READY = 5; // 0x5
     field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
+    field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm";
+    field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
   }
 
 }
@@ -34569,6 +34579,7 @@
     method public abstract void invalidate();
     method public void invalidateContentRect();
     method public boolean isTitleOptional();
+    method public void onWindowFocusChanged(boolean);
     method public abstract void setCustomView(android.view.View);
     method public abstract void setSubtitle(java.lang.CharSequence);
     method public abstract void setSubtitle(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index aa6f828..7e3e051 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -17118,6 +17118,10 @@
     ctor public MediaDrmException(java.lang.String);
   }
 
+  public class MediaDrmResetException extends java.lang.IllegalStateException {
+    ctor public MediaDrmResetException(java.lang.String);
+  }
+
   public final class MediaExtractor {
     ctor public MediaExtractor();
     method public boolean advance();
@@ -32843,6 +32847,7 @@
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
+    field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
     field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
     field public static final java.lang.String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
     field public static final java.lang.String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
@@ -32900,6 +32905,9 @@
     field public static final java.lang.String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
     field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
     field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
+    field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
+    field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
+    field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
     field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
 
@@ -33512,6 +33520,8 @@
     field public static final int SIM_STATE_PUK_REQUIRED = 3; // 0x3
     field public static final int SIM_STATE_READY = 5; // 0x5
     field public static final int SIM_STATE_UNKNOWN = 0; // 0x0
+    field public static final java.lang.String VVM_TYPE_CVVM = "vvm_type_cvvm";
+    field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
   }
 
 }
@@ -36850,6 +36860,7 @@
     method public abstract void invalidate();
     method public void invalidateContentRect();
     method public boolean isTitleOptional();
+    method public void onWindowFocusChanged(boolean);
     method public abstract void setCustomView(android.view.View);
     method public abstract void setSubtitle(java.lang.CharSequence);
     method public abstract void setSubtitle(int);
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 1461380..e178087 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -35,6 +35,9 @@
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
+import android.os.TransactionTooLargeException;
+import android.util.Log;
+
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.content.ReferrerIntent;
 
@@ -921,8 +924,13 @@
         info.writeToParcel(data, 0);
         compatInfo.writeToParcel(data, 0);
         data.writeInt(processState);
-        mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
-                IBinder.FLAG_ONEWAY);
+        try {
+            mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
+                    IBinder.FLAG_ONEWAY);
+        } catch (TransactionTooLargeException e) {
+            Log.e("CREATE_SERVICE", "Binder failure starting service; service=" + info);
+            throw e;
+        }
         data.recycle();
     }
 
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 08c5236..d83dfc5 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -1480,7 +1480,11 @@
      * Write the contents of the IntentFilter as an XML stream.
      */
     public void writeToXml(XmlSerializer serializer) throws IOException {
-        serializer.attribute(null, AUTO_VERIFY_STR, Boolean.toString(getAutoVerify()));
+
+        if (getAutoVerify()) {
+            serializer.attribute(null, AUTO_VERIFY_STR, Boolean.toString(true));
+        }
+
         int N = countActions();
         for (int i=0; i<N; i++) {
             serializer.startTag(null, ACTION_STR);
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 649fdb4..7bab35c 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -45,7 +45,7 @@
      * {@link #providerInfo} will be non-null.
      */
     public ActivityInfo activityInfo;
-    
+
     /**
      * The service that corresponds to this resolution match, if this resolution
      * is for a service. Exactly one of {@link #activityInfo},
@@ -64,21 +64,21 @@
      * The IntentFilter that was matched for this ResolveInfo.
      */
     public IntentFilter filter;
-    
+
     /**
      * The declared priority of this match.  Comes from the "priority"
      * attribute or, if not set, defaults to 0.  Higher values are a higher
      * priority.
      */
     public int priority;
-    
+
     /**
      * Order of result according to the user's preference.  If the user
      * has not set a preference for this result, the value is 0; higher
      * values are a higher priority.
      */
     public int preferredOrder;
-    
+
     /**
      * The system's evaluation of how well the activity matches the
      * IntentFilter.  This is a match constant, a combination of
@@ -86,7 +86,7 @@
      * and {@link IntentFilter#MATCH_ADJUSTMENT_MASK IntentFiler.MATCH_ADJUSTMENT_MASK}.
      */
     public int match;
-    
+
     /**
      * Only set when returned by
      * {@link PackageManager#queryIntentActivityOptions}, this tells you
@@ -94,29 +94,30 @@
      * first in the list, < 0 means it came from the generic Intent query.
      */
     public int specificIndex = -1;
-    
+
     /**
      * This filter has specified the Intent.CATEGORY_DEFAULT, meaning it
      * would like to be considered a default action that the user can
      * perform on this data.
      */
     public boolean isDefault;
-    
+
     /**
      * A string resource identifier (in the package's resources) of this
      * match's label.  From the "label" attribute or, if not set, 0.
      */
     public int labelRes;
-    
+
     /**
      * The actual string retrieve from <var>labelRes</var> or null if none
      * was provided.
      */
     public CharSequence nonLocalizedLabel;
-    
+
     /**
      * A drawable resource identifier (in the package's resources) of this
-     * match's icon.  From the "icon" attribute or, if not set, 0.
+     * match's icon.  From the "icon" attribute or, if not set, 0. It is
+     * set only if the icon can be obtained by resource id alone.
      */
     public int icon;
 
@@ -134,11 +135,21 @@
     public int targetUserId;
 
     /**
+     * Set to true if the icon cannot be obtained by resource ids alone.
+     * It is set to true for ResolveInfos from the managed profile: They need to
+     * have their icon badged, so it cannot be obtained by resource ids alone.
      * @hide
      */
     public boolean noResourceId;
 
     /**
+     * Same as {@link #icon} but it will always correspond to "icon" attribute
+     * regardless of {@link #noResourceId} value.
+     * @hide
+     */
+    public int iconResourceId;
+
+    /**
      * @hide Target comes from system process?
      */
     public boolean system;
@@ -159,10 +170,10 @@
      * Retrieve the current textual label associated with this resolution.  This
      * will call back on the given PackageManager to load the label from
      * the application.
-     * 
+     *
      * @param pm A PackageManager from which the label can be loaded; usually
      * the PackageManager from which you originally retrieved this item.
-     * 
+     *
      * @return Returns a CharSequence containing the resolutions's label.  If the
      * item does not have a label, its name is returned.
      */
@@ -191,33 +202,30 @@
         if (data != null) data = data.toString().trim();
         return data;
     }
-    
+
     /**
      * Retrieve the current graphical icon associated with this resolution.  This
      * will call back on the given PackageManager to load the icon from
      * the application.
-     * 
+     *
      * @param pm A PackageManager from which the icon can be loaded; usually
      * the PackageManager from which you originally retrieved this item.
-     * 
+     *
      * @return Returns a Drawable containing the resolution's icon.  If the
      * item does not have an icon, the default activity icon is returned.
      */
     public Drawable loadIcon(PackageManager pm) {
-        Drawable dr;
-        if (resolvePackageName != null && icon != 0) {
-            dr = pm.getDrawable(resolvePackageName, icon, null);
-            if (dr != null) {
-                return dr;
-            }
+        Drawable dr = null;
+        if (resolvePackageName != null && iconResourceId != 0) {
+            dr = pm.getDrawable(resolvePackageName, iconResourceId, null);
         }
         ComponentInfo ci = getComponentInfo();
-        ApplicationInfo ai = ci.applicationInfo;
-        if (icon != 0) {
-            dr = pm.getDrawable(ci.packageName, icon, ai);
-            if (dr != null) {
-                return dr;
-            }
+        if (dr == null && iconResourceId != 0) {
+            ApplicationInfo ai = ci.applicationInfo;
+            dr = pm.getDrawable(ci.packageName, iconResourceId, ai);
+        }
+        if (dr != null) {
+            return pm.getUserBadgedIcon(dr, new UserHandle(UserHandle.myUserId()));
         }
         return ci.loadIcon(pm);
     }
@@ -231,7 +239,7 @@
      * @return The icon associated with this match.
      */
     final int getIconResourceInternal() {
-        if (icon != 0) return icon;
+        if (iconResourceId != 0) return iconResourceId;
         final ComponentInfo ci = getComponentInfo();
         if (ci != null) {
             return ci.getIconResource();
@@ -298,6 +306,8 @@
         nonLocalizedLabel = orig.nonLocalizedLabel;
         icon = orig.icon;
         resolvePackageName = orig.resolvePackageName;
+        noResourceId = orig.noResourceId;
+        iconResourceId = orig.iconResourceId;
         system = orig.system;
         targetUserId = orig.targetUserId;
         handleAllWebDataURI = orig.handleAllWebDataURI;
@@ -362,6 +372,7 @@
         dest.writeInt(targetUserId);
         dest.writeInt(system ? 1 : 0);
         dest.writeInt(noResourceId ? 1 : 0);
+        dest.writeInt(iconResourceId);
         dest.writeInt(handleAllWebDataURI ? 1 : 0);
     }
 
@@ -408,9 +419,10 @@
         targetUserId = source.readInt();
         system = source.readInt() != 0;
         noResourceId = source.readInt() != 0;
+        iconResourceId = source.readInt();
         handleAllWebDataURI = source.readInt() != 0;
     }
-    
+
     public static class DisplayNameComparator
             implements Comparator<ResolveInfo> {
         public DisplayNameComparator(PackageManager pm) {
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index f8db6d9..c656fb8b 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -667,7 +667,7 @@
      * {@link android.hardware.camera2.params.StreamConfigurationMap#getHighSpeedVideoSizes }.
      * The fps range can be controlled via {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE android.control.aeTargetFpsRange}.</p>
      * <p>In this capability, the camera device will override aeMode, awbMode, and afMode to
-     * ON, ON, and CONTINUOUS_VIDEO, respectively. All post-processing block mode
+     * ON, AUTO, and CONTINUOUS_VIDEO, respectively. All post-processing block mode
      * controls will be overridden to be FAST. Therefore, no manual control of capture
      * and post-processing parameters is possible. All other controls operate the
      * same as when {@link CaptureRequest#CONTROL_MODE android.control.mode} == AUTO. This means that all other
@@ -1666,9 +1666,9 @@
      * <p>Enabling this disables control.aeMode, control.awbMode and
      * control.afMode controls; the camera device will ignore
      * those settings while USE_SCENE_MODE is active (except for
-     * FACE_PRIORITY scene mode). Other control entries are still
-     * active.  This setting can only be used if scene mode is
-     * supported (i.e. {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}
+     * FACE_PRIORITY scene mode). Other control entries are still active.
+     * This setting can only be used if scene mode is supported (i.e.
+     * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}
      * contain some modes other than DISABLED).</p>
      *
      * @see CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES
@@ -1940,6 +1940,40 @@
      */
     public static final int CONTROL_SCENE_MODE_HDR = 18;
 
+    /**
+     * <p>Same as FACE_PRIORITY scene mode, except that the camera
+     * device will choose higher sensivity values ({@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity})
+     * under low light conditions.</p>
+     * <p>The camera device may be tuned to expose the images in a reduced
+     * sensitivity range to produce the best quality images. For example,
+     * if the {@link CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE android.sensor.info.sensitivityRange} gives range of [100, 1600],
+     * the camera device auto-exposure routine tuning process may limit the actual
+     * exposure sensivity range to [100, 1200] to ensure that the noise level isn't
+     * exessive to compromise the image quality. Under this situation, the image under
+     * low light may be under-exposed when the sensor max exposure time (bounded by the
+     * {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE android.control.aeTargetFpsRange} when {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is one of the
+     * ON_* modes) and effecitve max sensitivity are reached. This scene mode allows the
+     * camera device auto-exposure routine to increase the sensitivity up to the max
+     * sensitivity specified by {@link CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE android.sensor.info.sensitivityRange} when the scene is too
+     * dark and the max exposure time is reached. The captured images may be noisier
+     * compared with the images captured in normal FACE_PRIORITY mode, therefore, it is
+     * recommended that the application only use this scene mode when it is capable of
+     * reducing the noise level of the captured images.</p>
+     * <p>Unlike the other scene modes, {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
+     * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}
+     * remain active when FACE_PRIORITY_LOW_LIGHT is set.</p>
+     *
+     * @see CaptureRequest#CONTROL_AE_MODE
+     * @see CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE
+     * @see CaptureRequest#CONTROL_AF_MODE
+     * @see CaptureRequest#CONTROL_AWB_MODE
+     * @see CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE
+     * @see CaptureRequest#SENSOR_SENSITIVITY
+     * @see CaptureRequest#CONTROL_SCENE_MODE
+     * @hide
+     */
+    public static final int CONTROL_SCENE_MODE_FACE_PRIORITY_LOW_LIGHT = 19;
+
     //
     // Enumeration values for CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
     //
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index bc625dd..9fa6687 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1448,9 +1448,9 @@
      * <p>Scene modes are custom camera modes optimized for a certain set of conditions and
      * capture settings.</p>
      * <p>This is the mode that that is active when
-     * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY,
-     * these modes will disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
-     * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} while in use.</p>
+     * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY, these modes will
+     * disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}, {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}
+     * while in use.</p>
      * <p>The interpretation and implementation of these scene modes is left
      * to the implementor of the camera device. Their behavior will not be
      * consistent across all devices, and any given device may only implement
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index da216aa..b1fb615 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1960,9 +1960,9 @@
      * <p>Scene modes are custom camera modes optimized for a certain set of conditions and
      * capture settings.</p>
      * <p>This is the mode that that is active when
-     * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY,
-     * these modes will disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
-     * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} while in use.</p>
+     * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY, these modes will
+     * disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}, {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}
+     * while in use.</p>
      * <p>The interpretation and implementation of these scene modes is left
      * to the implementor of the camera device. Their behavior will not be
      * consistent across all devices, and any given device may only implement
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index d165240..eb6e1c2 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1165,25 +1165,23 @@
         public static final int EVENT_USER_FOREGROUND = 0x0008;
         // Event for connectivity changed.
         public static final int EVENT_CONNECTIVITY_CHANGED = 0x0009;
-        // Event for significant motion taking us out of idle mode.
-        public static final int EVENT_SIGNIFICANT_MOTION = 0x000a;
         // Event for becoming active taking us out of idle mode.
-        public static final int EVENT_ACTIVE = 0x000b;
+        public static final int EVENT_ACTIVE = 0x000a;
         // Event for a package being installed.
-        public static final int EVENT_PACKAGE_INSTALLED = 0x000c;
+        public static final int EVENT_PACKAGE_INSTALLED = 0x000b;
         // Event for a package being uninstalled.
-        public static final int EVENT_PACKAGE_UNINSTALLED = 0x000d;
+        public static final int EVENT_PACKAGE_UNINSTALLED = 0x000c;
         // Event for a package being uninstalled.
-        public static final int EVENT_ALARM = 0x000e;
+        public static final int EVENT_ALARM = 0x000d;
         // Record that we have decided we need to collect new stats data.
-        public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000f;
+        public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000e;
         // Event for a package becoming inactive due to being unused for a period of time.
-        public static final int EVENT_PACKAGE_INACTIVE = 0x0010;
+        public static final int EVENT_PACKAGE_INACTIVE = 0x000f;
         // Event for a package becoming active due to an interaction.
-        public static final int EVENT_PACKAGE_ACTIVE = 0x0011;
+        public static final int EVENT_PACKAGE_ACTIVE = 0x0010;
 
         // Number of event types.
-        public static final int EVENT_COUNT = 0x0012;
+        public static final int EVENT_COUNT = 0x0011;
         // Mask to extract out only the type part of the event.
         public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
 
@@ -1840,12 +1838,12 @@
 
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
             "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
-            "motion", "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active"
+            "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active"
     };
 
     public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
             "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
-            "Esm", "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa"
+            "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa"
     };
 
     /**
@@ -4017,8 +4015,10 @@
             if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
                 sb.setLength(0);
                 sb.append(prefix);
-                sb.append("    Total cpu time: ");
-                formatTimeMs(sb, (userCpuTimeUs + systemCpuTimeUs) / 1000);
+                sb.append("    Total cpu time: u=");
+                formatTimeMs(sb, userCpuTimeUs / 1000);
+                sb.append("s=");
+                formatTimeMs(sb, systemCpuTimeUs / 1000);
                 pw.println(sb.toString());
             }
 
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index 268295d..fe4aa13 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -28,4 +28,5 @@
     int[] getAppIdTempWhitelist();
     boolean isPowerSaveWhitelistApp(String name);
     void addPowerSaveTempWhitelistApp(String name, long duration, int userId);
+    void exitIdle(String reason);
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index dbb5146..f9c50f3 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -635,8 +635,8 @@
             if ((debugFlags & Zygote.DEBUG_ENABLE_JIT) != 0) {
                 argsForZygote.add("--enable-jit");
             }
-            if ((debugFlags & Zygote.DEBUG_GENERATE_CFI) != 0) {
-                argsForZygote.add("--generate-cfi");
+            if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {
+                argsForZygote.add("--generate-debug-info");
             }
             if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
                 argsForZygote.add("--enable-assert");
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 3fb93c4..62c28ac 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -81,8 +81,8 @@
 
     public static final int KM_TAG_ASSOCIATED_DATA = KM_BYTES | 1000;
     public static final int KM_TAG_NONCE = KM_BYTES | 1001;
-    public static final int KM_TAG_AUTH_TOKEN = KM_BYTES | 1003;
-    public static final int KM_TAG_MAC_LENGTH = KM_INT | 1004;
+    public static final int KM_TAG_AUTH_TOKEN = KM_BYTES | 1002;
+    public static final int KM_TAG_MAC_LENGTH = KM_INT | 1003;
 
     // Algorithm values.
     public static final int KM_ALGORITHM_RSA = 1;
@@ -191,8 +191,9 @@
     public static final int KM_ERROR_MISSING_NONCE = -51;
     public static final int KM_ERROR_INVALID_NONCE = -52;
     public static final int KM_ERROR_MISSING_MAC_LENGTH = -53;
-    public static final int KM_ERROR_RESCOPABLE_KEY_NOT_USABLE = -54;
+    public static final int KM_ERROR_KEY_RATE_LIMIT_EXCEEDED = -54;
     public static final int KM_ERROR_CALLER_NONCE_PROHIBITED = -55;
+    public static final int KM_ERROR_KEY_MAX_OPS_EXCEEDED = -56;
     public static final int KM_ERROR_UNIMPLEMENTED = -100;
     public static final int KM_ERROR_VERSION_MISMATCH = -101;
     public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 8c6cd09..0309d24 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -41,6 +41,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -463,15 +464,28 @@
             ParceledListSlice<StatusBarNotification> parceledList = getNotificationInterface()
                     .getActiveNotificationsFromListener(mWrapper, keys, trim);
             List<StatusBarNotification> list = parceledList.getList();
-
+            ArrayList<StatusBarNotification> corruptNotifications = null;
             int N = list.size();
             for (int i = 0; i < N; i++) {
-                Notification notification = list.get(i).getNotification();
-                Builder.rebuild(getContext(), notification);
-                // convert icon metadata to legacy format for older clients
-                createLegacyIconExtras(notification);
+                StatusBarNotification sbn = list.get(i);
+                Notification notification = sbn.getNotification();
+                try {
+                    Builder.rebuild(getContext(), notification);
+                    // convert icon metadata to legacy format for older clients
+                    createLegacyIconExtras(notification);
+                } catch (IllegalArgumentException e) {
+                    if (corruptNotifications == null) {
+                        corruptNotifications = new ArrayList<>(N);
+                    }
+                    corruptNotifications.add(sbn);
+                    Log.w(TAG, "onNotificationPosted: can't rebuild notification from " +
+                            sbn.getPackageName());
+                }
             }
-            return list.toArray(new StatusBarNotification[N]);
+            if (corruptNotifications != null) {
+                list.removeAll(corruptNotifications);
+            }
+            return list.toArray(new StatusBarNotification[list.size()]);
         } catch (android.os.RemoteException ex) {
             Log.v(TAG, "Unable to contact notification manager", ex);
         }
@@ -671,16 +685,28 @@
                 Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification", e);
                 return;
             }
-            Notification.Builder.rebuild(getContext(), sbn.getNotification());
 
-            // convert icon metadata to legacy format for older clients
-            createLegacyIconExtras(sbn.getNotification());
+            try {
+                Notification.Builder.rebuild(getContext(), sbn.getNotification());
+                // convert icon metadata to legacy format for older clients
+                createLegacyIconExtras(sbn.getNotification());
+            } catch (IllegalArgumentException e) {
+                // drop corrupt notification
+                sbn = null;
+                Log.w(TAG, "onNotificationPosted: can't rebuild notification from " +
+                        sbn.getPackageName());
+            }
 
             // protect subclass from concurrent modifications of (@link mNotificationKeys}.
             synchronized (mWrapper) {
                 applyUpdate(update);
                 try {
-                    NotificationListenerService.this.onNotificationPosted(sbn, mRankingMap);
+                    if (sbn != null) {
+                        NotificationListenerService.this.onNotificationPosted(sbn, mRankingMap);
+                    } else {
+                        // still pass along the ranking map, it may contain other information
+                        NotificationListenerService.this.onNotificationRankingUpdate(mRankingMap);
+                    }
                 } catch (Throwable t) {
                     Log.w(TAG, "Error running onNotificationPosted", t);
                 }
diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java
index 80dcecc..ea979c8 100644
--- a/core/java/android/view/ActionMode.java
+++ b/core/java/android/view/ActionMode.java
@@ -261,6 +261,16 @@
     public abstract MenuInflater getMenuInflater();
 
     /**
+     * Called when the window containing the view that started this action mode gains or loses
+     * focus.
+     *
+     * @param hasWindowFocus True if the window containing the view that started this action mode
+     *        now has focus, false otherwise.
+     *
+     */
+    public void onWindowFocusChanged(boolean hasWindowFocus) {}
+
+    /**
      * Returns whether the UI presenting this action mode can take focus or not.
      * This is used by internal components within the framework that would otherwise
      * present an action mode UI that requires focus, such as an EditText as a custom view.
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 2f5c9e2..7db88af 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -298,14 +298,27 @@
      * Notify the host application to handle a SSL client certificate
      * request. The host application is responsible for showing the UI
      * if desired and providing the keys. There are three ways to
-     * respond: proceed(), cancel() or ignore(). Webview remembers the
-     * response if proceed() or cancel() is called and does not
-     * call onReceivedClientCertRequest() again for the same host and port
-     * pair. Webview does not remember the response if ignore() is called.
+     * respond: proceed(), cancel() or ignore(). Webview stores the response
+     * in memory (for the life of the application) if proceed() or cancel() is
+     * called and does not call onReceivedClientCertRequest() again for the
+     * same host and port pair. Webview does not store the response if ignore()
+     * is called.
      *
      * This method is called on the UI thread. During the callback, the
      * connection is suspended.
      *
+     * For most use cases, the application program should implement the
+     * {@link android.security.KeyChainAliasCallback} interface and pass it to
+     * {@link android.security.KeyChain.choosePrivateKeyAlias} to start an
+     * activity for the user to choose the proper alias. The keychain activity will
+     * provide the alias through the callback method in the implemented interface. Next
+     * the application should create an async task to call
+     * {@link android.security.KeyChain.getPrivateKey} to receive the key.
+     *
+     * An example implementation of client certificates can be seen at
+     * <A href="https://android.googlesource.com/platform/packages/apps/Browser/+/android-5.1.1_r1/src/com/android/browser/Tab.java">
+     * AOSP Browser</a>
+     *
      * The default behavior is to cancel, returning no client certificate.
      *
      * @param view The WebView that is initiating the callback
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index b4ef58a..3b9aca8 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -96,49 +96,27 @@
         public MissingWebViewPackageException(Exception e) { super(e); }
     }
 
-    /** @hide */
-    public static String[] getWebViewPackageNames() {
-        return AppGlobals.getInitialApplication().getResources().getStringArray(
-                com.android.internal.R.array.config_webViewPackageNames);
-    }
-
-    // TODO (gsennton) remove when committing webview xts test change
     public static String getWebViewPackageName() {
-        String[] webViewPackageNames = getWebViewPackageNames();
-        return webViewPackageNames[webViewPackageNames.length-1];
+        return AppGlobals.getInitialApplication().getString(
+                com.android.internal.R.string.config_webViewPackageName);
     }
 
-    /**
-     * Return the package info of the first package in the webview priority list that contains
-     * webview.
-     *
-     * @hide
-     */
-    public static PackageInfo findPreferredWebViewPackage() {
+    private static PackageInfo fetchPackageInfo() {
         PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
-
-        for (String packageName : getWebViewPackageNames()) {
-            try {
-                PackageInfo packageInfo = pm.getPackageInfo(packageName,
-                    PackageManager.GET_META_DATA);
-                ApplicationInfo applicationInfo = packageInfo.applicationInfo;
-
-                // If the correct flag is set the package contains webview.
-                if (getWebViewLibrary(applicationInfo) != null) {
-                    return packageInfo;
-                }
-            } catch (PackageManager.NameNotFoundException e) {
-            }
+        try {
+            return pm.getPackageInfo(getWebViewPackageName(), PackageManager.GET_META_DATA);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new MissingWebViewPackageException(e);
         }
-        throw new MissingWebViewPackageException("Could not find a loadable WebView package");
     }
 
     // throws MissingWebViewPackageException
     private static ApplicationInfo getWebViewApplicationInfo() {
-        if (sPackageInfo == null)
-            return findPreferredWebViewPackage().applicationInfo;
-        else
+        if (sPackageInfo == null) {
+            return fetchPackageInfo().applicationInfo;
+        } else {
             return sPackageInfo.applicationInfo;
+        }
     }
 
     private static String getWebViewLibrary(ApplicationInfo ai) {
@@ -153,10 +131,10 @@
 
     /**
      * Load the native library for the given package name iff that package
-     * name is the same as the one providing the current webview.
+     * name is the same as the one providing the webview.
      */
     public static int loadWebViewNativeLibraryFromPackage(String packageName) {
-        sPackageInfo = findPreferredWebViewPackage();
+        sPackageInfo = fetchPackageInfo();
         if (packageName != null && packageName.equals(sPackageInfo.packageName)) {
             return loadNativeLibrary();
         }
@@ -202,7 +180,7 @@
     private static Class<WebViewFactoryProvider> getProviderClass() {
         try {
             // First fetch the package info so we can log the webview package version.
-            sPackageInfo = findPreferredWebViewPackage();
+            sPackageInfo = fetchPackageInfo();
             Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " +
                 sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")");
 
@@ -241,8 +219,8 @@
         try {
             // Construct a package context to load the Java code into the current app.
             Context webViewContext = initialApplication.createPackageContext(
-                sPackageInfo.packageName,
-                Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+                    sPackageInfo.packageName,
+                    Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
             initialApplication.getAssets().addAssetPath(
                     webViewContext.getApplicationInfo().sourceDir);
             ClassLoader clazzLoader = webViewContext.getClassLoader();
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
index a15080e..ebb54ff 100644
--- a/core/java/android/widget/Chronometer.java
+++ b/core/java/android/widget/Chronometer.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.os.Handler;
 import android.os.Message;
@@ -24,6 +25,7 @@
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.RemoteViews.RemoteView;
 
 import java.util.Formatter;
@@ -58,6 +60,7 @@
     }
 
     private long mBase;
+    private long mNow; // the currently displayed time
     private boolean mVisible;
     private boolean mStarted;
     private boolean mRunning;
@@ -224,6 +227,7 @@
     }
 
     private synchronized void updateText(long now) {
+        mNow = now;
         long seconds = now - mBase;
         seconds /= 1000;
         String text = DateUtils.formatElapsedTime(mRecycle, seconds);
@@ -279,6 +283,60 @@
         }
     }
 
+    private static final int MIN_IN_SEC = 60;
+    private static final int HOUR_IN_SEC = MIN_IN_SEC*60;
+    private static String formatDuration(long ms) {
+        final Resources res = Resources.getSystem();
+        final StringBuilder text = new StringBuilder();
+
+        int duration = (int) (ms / DateUtils.SECOND_IN_MILLIS);
+        if (duration < 0) {
+            duration = -duration;
+        }
+
+        int h = 0;
+        int m = 0;
+
+        if (duration >= HOUR_IN_SEC) {
+            h = duration / HOUR_IN_SEC;
+            duration -= h * HOUR_IN_SEC;
+        }
+        if (duration >= MIN_IN_SEC) {
+            m = duration / MIN_IN_SEC;
+            duration -= m * MIN_IN_SEC;
+        }
+        int s = duration;
+
+        try {
+            if (h > 0) {
+                text.append(res.getQuantityString(
+                        com.android.internal.R.plurals.duration_hours, h, h));
+            }
+            if (m > 0) {
+                if (text.length() > 0) {
+                    text.append(' ');
+                }
+                text.append(res.getQuantityString(
+                        com.android.internal.R.plurals.duration_minutes, m, m));
+            }
+
+            if (text.length() > 0) {
+                text.append(' ');
+            }
+            text.append(res.getQuantityString(
+                    com.android.internal.R.plurals.duration_seconds, s, s));
+        } catch (Resources.NotFoundException e) {
+            // Ignore; plurals throws an exception for an untranslated quantity for a given locale.
+            return null;
+        }
+        return text.toString();
+    }
+
+    @Override
+    public CharSequence getContentDescription() {
+        return formatDuration(mNow - mBase);
+    }
+
     @Override
     public CharSequence getAccessibilityClassName() {
         return Chronometer.class.getName();
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 339038e..affc5da 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -522,7 +522,7 @@
         View baselineView = null;
         LayoutParams baselineParams = null;
         for (int i = 0; i < count; i++) {
-            final View child = views[i];
+            final View child = getChildAt(i);
             if (child.getVisibility() != GONE) {
                 final LayoutParams childParams = (LayoutParams) child.getLayoutParams();
                 if (baselineView == null || baselineParams == null
@@ -548,9 +548,9 @@
 
             if (offsetHorizontalAxis) {
                 for (int i = 0; i < count; i++) {
-                    final View child = views[i];
+                    View child = getChildAt(i);
                     if (child.getVisibility() != GONE) {
-                        final LayoutParams params = (LayoutParams) child.getLayoutParams();
+                        LayoutParams params = (LayoutParams) child.getLayoutParams();
                         final int[] rules = params.getRules(layoutDirection);
                         if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {
                             centerHorizontal(child, params, width);
@@ -578,9 +578,9 @@
 
             if (offsetVerticalAxis) {
                 for (int i = 0; i < count; i++) {
-                    final View child = views[i];
+                    View child = getChildAt(i);
                     if (child.getVisibility() != GONE) {
-                        final LayoutParams params = (LayoutParams) child.getLayoutParams();
+                        LayoutParams params = (LayoutParams) child.getLayoutParams();
                         final int[] rules = params.getRules(layoutDirection);
                         if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {
                             centerVertical(child, params, height);
@@ -607,9 +607,9 @@
             final int verticalOffset = contentBounds.top - top;
             if (horizontalOffset != 0 || verticalOffset != 0) {
                 for (int i = 0; i < count; i++) {
-                    final View child = views[i];
+                    View child = getChildAt(i);
                     if (child.getVisibility() != GONE && child != ignore) {
-                        final LayoutParams params = (LayoutParams) child.getLayoutParams();
+                        LayoutParams params = (LayoutParams) child.getLayoutParams();
                         if (horizontalGravity) {
                             params.mLeft += horizontalOffset;
                             params.mRight += horizontalOffset;
@@ -626,9 +626,9 @@
         if (isLayoutRtl()) {
             final int offsetWidth = myWidth - width;
             for (int i = 0; i < count; i++) {
-                final View child = views[i];
+                View child = getChildAt(i);
                 if (child.getVisibility() != GONE) {
-                    final LayoutParams params = (LayoutParams) child.getLayoutParams();
+                    LayoutParams params = (LayoutParams) child.getLayoutParams();
                     params.mLeft -= offsetWidth;
                     params.mRight -= offsetWidth;
                 }
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index c1ec6e6..2a13c76 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -613,15 +613,17 @@
                     ri.activityInfo = ai;
                     UserManager userManager =
                             (UserManager) getSystemService(Context.USER_SERVICE);
-                    if (userManager.isManagedProfile()) {
-                        ri.noResourceId = true;
-                    }
                     if (ii instanceof LabeledIntent) {
                         LabeledIntent li = (LabeledIntent)ii;
                         ri.resolvePackageName = li.getSourcePackage();
                         ri.labelRes = li.getLabelResource();
                         ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                         ri.icon = li.getIconResource();
+                        ri.iconResourceId = ri.icon;
+                    }
+                    if (userManager.isManagedProfile()) {
+                        ri.noResourceId = true;
+                        ri.icon = 0;
                     }
                     mCallerTargets.add(new DisplayResolveInfo(ii, ri,
                             ri.loadLabel(pm), null, ii));
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 929cacd..6f0cec6 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -116,7 +116,7 @@
     void noteWifiRadioPowerState(int powerState, long timestampNs);
     void noteNetworkInterfaceType(String iface, int type);
     void noteNetworkStatsEnabled();
-    void noteDeviceIdleMode(boolean enabled, boolean fromActive, boolean fromMotion);
+    void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid);
     void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
     long getAwakeTimeBattery();
     long getAwakeTimePlugged();
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 39c86f9..e14f058 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1186,15 +1186,17 @@
                         ri.activityInfo = ai;
                         UserManager userManager =
                                 (UserManager) getSystemService(Context.USER_SERVICE);
-                        if (userManager.isManagedProfile()) {
-                            ri.noResourceId = true;
-                        }
                         if (ii instanceof LabeledIntent) {
                             LabeledIntent li = (LabeledIntent)ii;
                             ri.resolvePackageName = li.getSourcePackage();
                             ri.labelRes = li.getLabelResource();
                             ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                             ri.icon = li.getIconResource();
+                            ri.iconResourceId = ri.icon;
+                        }
+                        if (userManager.isManagedProfile()) {
+                            ri.noResourceId = true;
+                            ri.icon = 0;
                         }
                         addResolveInfo(new DisplayResolveInfo(ii, ri,
                                 ri.loadLabel(getPackageManager()), null, ii));
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 07d1fc8..229079f 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -95,7 +95,8 @@
 public final class BatteryStatsImpl extends BatteryStats {
     private static final String TAG = "BatteryStatsImpl";
     private static final boolean DEBUG = false;
-    private static final boolean DEBUG_ENERGY = false;
+    public static final boolean DEBUG_ENERGY = false;
+    private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY || false;
     private static final boolean DEBUG_HISTORY = false;
     private static final boolean USE_OLD_HISTORY = false;   // for debugging.
 
@@ -105,7 +106,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 127 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 128 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -151,6 +152,9 @@
             BatteryCallback cb = mCallback;
             switch (msg.what) {
                 case MSG_UPDATE_WAKELOCKS:
+                    synchronized (BatteryStatsImpl.this) {
+                        updateCpuTimeLocked();
+                    }
                     if (cb != null) {
                         cb.batteryNeedsCpuUpdate();
                     }
@@ -178,6 +182,7 @@
 
     public interface ExternalStatsSync {
         void scheduleSync(String reason);
+        void scheduleWifiSync(String reason);
     }
 
     public final MyHandler mHandler;
@@ -2503,12 +2508,11 @@
         boolean unpluggedScreenOff = unplugged && screenOff;
         if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) {
             updateKernelWakelocksLocked();
-            requestWakelockCpuUpdate();
-            if (!unpluggedScreenOff) {
-                // We are switching to no longer tracking wake locks, but we want
-                // the next CPU update we receive to take them in to account.
-                mDistributeWakelockCpu = true;
+            if (DEBUG_ENERGY_CPU) {
+                Slog.d(TAG, "Updating cpu time because screen is now " +
+                        (unpluggedScreenOff ? "off" : "on"));
             }
+            updateCpuTimeLocked();
             mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime);
         }
     }
@@ -2772,10 +2776,14 @@
             mWakeLockNesting++;
         }
         if (uid >= 0) {
-            //if (uid == 0) {
-            //    Slog.wtf(TAG, "Acquiring wake lock from root: " + name);
-            //}
-            requestWakelockCpuUpdate();
+            if (mOnBatteryScreenOffTimeBase.isRunning()) {
+                // We only update the cpu time when a wake lock is acquired if the screen is off.
+                // If the screen is on, we don't distribute the power amongst partial wakelocks.
+                if (DEBUG_ENERGY_CPU) {
+                    Slog.d(TAG, "Updating cpu time because of +wake_lock");
+                }
+                requestWakelockCpuUpdate();
+            }
             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
         }
     }
@@ -2805,7 +2813,12 @@
             }
         }
         if (uid >= 0) {
-            requestWakelockCpuUpdate();
+            if (mOnBatteryScreenOffTimeBase.isRunning()) {
+                if (DEBUG_ENERGY_CPU) {
+                    Slog.d(TAG, "Updating cpu time because of -wake_lock");
+                }
+                requestWakelockCpuUpdate();
+            }
             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
         }
     }
@@ -2874,46 +2887,14 @@
         addHistoryRecordLocked(elapsedRealtime, uptime);
     }
 
-    public int startAddingCpuLocked() {
+    public boolean startAddingCpuLocked() {
         mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
-
-        if (!mOnBatteryInternal) {
-            return -1;
-        }
-
-        final int N = mPartialTimers.size();
-        if (N == 0) {
-            mLastPartialTimers.clear();
-            mDistributeWakelockCpu = false;
-            return 0;
-        }
-
-        if (!mOnBatteryScreenOffTimeBase.isRunning() && !mDistributeWakelockCpu) {
-            return 0;
-        }
-
-        mDistributeWakelockCpu = false;
-
-        // How many timers should consume CPU?  Only want to include ones
-        // that have already been in the list.
-        for (int i=0; i<N; i++) {
-            StopwatchTimer st = mPartialTimers.get(i);
-            if (st.mInList) {
-                Uid uid = st.mUid;
-                // We don't include the system UID, because it so often
-                // holds wake locks at one request or another of an app.
-                if (uid != null && uid.mUid != Process.SYSTEM_UID) {
-                    return 50;
-                }
-            }
-        }
-
-        return 0;
+        return mOnBatteryInternal;
     }
 
-    public void finishAddingCpuLocked(int perc, int remainUTime, int remainSTtime,
-            int totalUTime, int totalSTime, int statUserTime, int statSystemTime,
-            int statIOWaitTime, int statIrqTime, int statSoftIrqTime, int statIdleTime) {
+    public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime,
+                                      int statSystemTime, int statIOWaitTime, int statIrqTime,
+                                      int statSoftIrqTime, int statIdleTime) {
         if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime
                 + " user=" + statUserTime + " sys=" + statSystemTime
                 + " io=" + statIOWaitTime + " irq=" + statIrqTime
@@ -2926,70 +2907,6 @@
         mCurStepStatIrqTime += statIrqTime;
         mCurStepStatSoftIrqTime += statSoftIrqTime;
         mCurStepStatIdleTime += statIdleTime;
-
-        final int N = mPartialTimers.size();
-        if (perc != 0) {
-            int num = 0;
-            for (int i=0; i<N; i++) {
-                StopwatchTimer st = mPartialTimers.get(i);
-                if (st.mInList) {
-                    Uid uid = st.mUid;
-                    // We don't include the system UID, because it so often
-                    // holds wake locks at one request or another of an app.
-                    if (uid != null && uid.mUid != Process.SYSTEM_UID) {
-                        num++;
-                    }
-                }
-            }
-            if (num != 0) {
-                for (int i=0; i<N; i++) {
-                    StopwatchTimer st = mPartialTimers.get(i);
-                    if (st.mInList) {
-                        Uid uid = st.mUid;
-                        if (uid != null && uid.mUid != Process.SYSTEM_UID) {
-                            int myUTime = remainUTime/num;
-                            int mySTime = remainSTtime/num;
-                            remainUTime -= myUTime;
-                            remainSTtime -= mySTime;
-                            num--;
-                            Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
-                            proc.addCpuTimeLocked(myUTime, mySTime);
-                        }
-                    }
-                }
-            }
-
-            // Just in case, collect any lost CPU time.
-            if (remainUTime != 0 || remainSTtime != 0) {
-                Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
-                if (uid != null) {
-                    Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
-                    proc.addCpuTimeLocked(remainUTime, remainSTtime);
-                }
-            }
-        }
-
-        final int NL = mLastPartialTimers.size();
-        boolean diff = N != NL;
-        for (int i=0; i<NL && !diff; i++) {
-            diff |= mPartialTimers.get(i) != mLastPartialTimers.get(i);
-        }
-        if (!diff) {
-            for (int i=0; i<NL; i++) {
-                mPartialTimers.get(i).mInList = true;
-            }
-            return;
-        }
-
-        for (int i=0; i<NL; i++) {
-            mLastPartialTimers.get(i).mInList = false;
-        }
-        mLastPartialTimers.clear();
-        for (int i=0; i<N; i++) {
-            StopwatchTimer st = mPartialTimers.get(i);
-            st.mInList = true;
-            mLastPartialTimers.add(st);
-        }
     }
 
     public void noteProcessDiedLocked(int uid, int pid) {
@@ -3271,11 +3188,11 @@
         }
     }
 
-    public void noteDeviceIdleModeLocked(boolean enabled, boolean fromActive, boolean fromMotion) {
+    public void noteDeviceIdleModeLocked(boolean enabled, String activeReason, int activeUid) {
         final long elapsedRealtime = SystemClock.elapsedRealtime();
         final long uptime = SystemClock.uptimeMillis();
         boolean nowIdling = enabled;
-        if (mDeviceIdling && !enabled && !fromActive && !fromMotion) {
+        if (mDeviceIdling && !enabled && activeReason == null) {
             // We don't go out of general idling mode until explicitly taken out of
             // device idle through going active or significant motion.
             nowIdling = true;
@@ -3293,14 +3210,8 @@
         }
         if (mDeviceIdleModeEnabled != enabled) {
             mDeviceIdleModeEnabled = enabled;
-            if (fromMotion) {
-                addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SIGNIFICANT_MOTION,
-                        "", 0);
-            }
-            if (fromActive) {
-                addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
-                        "", 0);
-            }
+            addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
+                    activeReason != null ? activeReason : "", activeUid);
             if (enabled) {
                 mHistoryCur.states2 |= HistoryItem.STATE2_DEVICE_IDLE_FLAG;
                 if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode enabled to: "
@@ -3580,7 +3491,7 @@
             addHistoryRecordLocked(elapsedRealtime, uptime);
             mWifiOn = true;
             mWifiOnTimer.startRunningLocked(elapsedRealtime);
-            scheduleSyncExternalStatsLocked("wifi-off");
+            scheduleSyncExternalWifiStatsLocked("wifi-off");
         }
     }
 
@@ -3594,7 +3505,7 @@
             addHistoryRecordLocked(elapsedRealtime, uptime);
             mWifiOn = false;
             mWifiOnTimer.stopRunningLocked(elapsedRealtime);
-            scheduleSyncExternalStatsLocked("wifi-on");
+            scheduleSyncExternalWifiStatsLocked("wifi-on");
         }
     }
 
@@ -3846,7 +3757,7 @@
                 int uid = mapUid(ws.get(i));
                 getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime);
             }
-            scheduleSyncExternalStatsLocked("wifi-running");
+            scheduleSyncExternalWifiStatsLocked("wifi-running");
         } else {
             Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
         }
@@ -3885,7 +3796,7 @@
                 int uid = mapUid(ws.get(i));
                 getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime);
             }
-            scheduleSyncExternalStatsLocked("wifi-stopped");
+            scheduleSyncExternalWifiStatsLocked("wifi-stopped");
         } else {
             Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
         }
@@ -3900,7 +3811,7 @@
             }
             mWifiState = wifiState;
             mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
-            scheduleSyncExternalStatsLocked("wifi-state");
+            scheduleSyncExternalWifiStatsLocked("wifi-state");
         }
     }
 
@@ -7632,6 +7543,10 @@
      * @param info The energy information from the WiFi controller.
      */
     public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
+        if (DEBUG_ENERGY) {
+            Slog.d(TAG, "Updating wifi stats");
+        }
+
         final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
         NetworkStats delta = null;
         try {
@@ -7829,6 +7744,10 @@
      * Distribute Cell radio energy info and network traffic to apps.
      */
     public void updateMobileRadioStateLocked(final long elapsedRealtimeMs) {
+        if (DEBUG_ENERGY) {
+            Slog.d(TAG, "Updating mobile radio stats");
+        }
+
         NetworkStats delta = null;
         try {
             if (!ArrayUtils.isEmpty(mMobileIfaces)) {
@@ -7901,6 +7820,10 @@
      * @param info The energy information from the bluetooth controller.
      */
     public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) {
+        if (DEBUG_ENERGY) {
+            Slog.d(TAG, "Updating bluetooth stats");
+        }
+
         if (info != null && mOnBatteryInternal) {
             mHasBluetoothEnergyReporting = true;
             mBluetoothActivityCounters[CONTROLLER_RX_TIME].addCountLocked(
@@ -7959,30 +7882,196 @@
         }
     }
 
+    // We use an anonymous class to access these variables,
+    // so they can't live on the stack or they'd have to be
+    // final MutableLong objects (more allocations).
+    // Used in updateCpuTimeLocked().
+    long mTempTotalCpuUserTimeUs;
+    long mTempTotalCpuSystemTimeUs;
+
     /**
-     * Read and distribute CPU usage across apps.
+     * Read and distribute CPU usage across apps. If their are partial wakelocks being held
+     * and we are on battery with screen off, we give more of the cpu time to those apps holding
+     * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
      */
-    public void updateCpuTimeLocked(boolean firstTime) {
+    public void updateCpuTimeLocked() {
+        if (DEBUG_ENERGY_CPU) {
+            Slog.d(TAG, "!Cpu updating!");
+        }
+
+        // Holding a wakelock costs more than just using the cpu.
+        // Currently, we assign only half the cpu time to an app that is running but
+        // not holding a wakelock. The apps holding wakelocks get the rest of the blame.
+        // If no app is holding a wakelock, then the distribution is normal.
+        final int wakelockWeight = 50;
+
+        // Read the time spent at various cpu frequencies.
         final int cpuSpeedSteps = getCpuSpeedSteps();
         final long[] cpuSpeeds = mKernelCpuSpeedReader.readDelta();
-        KernelUidCpuTimeReader.Callback callback = null;
-        if (mOnBatteryInternal && !firstTime) {
-            callback = new KernelUidCpuTimeReader.Callback() {
-                @Override
-                public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
-                    final Uid u = getUidStatsLocked(mapUid(uid));
-                    u.mUserCpuTime.addCountLocked(userTimeUs);
-                    u.mSystemCpuTime.addCountLocked(systemTimeUs);
-                    for (int i = 0; i < cpuSpeedSteps; i++) {
-                        if (u.mSpeedBins[i] == null) {
-                            u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase);
-                        }
-                        u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]);
-                    }
+
+        int numWakelocks = 0;
+
+        // Calculate how many wakelocks we have to distribute amongst. The system is excluded.
+        // Only distribute cpu power to wakelocks if the screen is off and we're on battery.
+        final int numPartialTimers = mPartialTimers.size();
+        if (mOnBatteryScreenOffTimeBase.isRunning()) {
+            for (int i = 0; i < numPartialTimers; i++) {
+                final StopwatchTimer timer = mPartialTimers.get(i);
+                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
+                    // Since the collection and blaming of wakelocks can be scheduled to run after
+                    // some delay, the mPartialTimers list may have new entries. We can't blame
+                    // the newly added timer for past cpu time, so we only consider timers that
+                    // were present for one round of collection. Once a timer has gone through
+                    // a round of collection, its mInList field is set to true.
+                    numWakelocks++;
                 }
-            };
+            }
         }
-        mKernelUidCpuTimeReader.readDelta(callback);
+
+        final int numWakelocksF = numWakelocks;
+        mTempTotalCpuUserTimeUs = 0;
+        mTempTotalCpuSystemTimeUs = 0;
+
+        // Read the CPU data for each UID. This will internally generate a snapshot so next time
+        // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
+        // we just ignore the data.
+        final long startTimeMs = SystemClock.elapsedRealtime();
+        mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
+                new KernelUidCpuTimeReader.Callback() {
+                    @Override
+                    public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
+                        final Uid u = getUidStatsLocked(mapUid(uid));
+
+                        // Accumulate the total system and user time.
+                        mTempTotalCpuUserTimeUs += userTimeUs;
+                        mTempTotalCpuSystemTimeUs += systemTimeUs;
+
+                        StringBuilder sb = null;
+                        if (DEBUG_ENERGY_CPU) {
+                            sb = new StringBuilder();
+                            sb.append("  got time for uid=").append(u.mUid).append(": u=");
+                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
+                            sb.append(" s=");
+                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+                            sb.append("\n");
+                        }
+
+                        if (numWakelocksF > 0) {
+                            // We have wakelocks being held, so only give a portion of the
+                            // time to the process. The rest will be distributed among wakelock
+                            // holders.
+                            userTimeUs = (userTimeUs * wakelockWeight) / 100;
+                            systemTimeUs = (systemTimeUs * wakelockWeight) / 100;
+                        }
+
+                        if (sb != null) {
+                            sb.append("  adding to uid=").append(u.mUid).append(": u=");
+                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
+                            sb.append(" s=");
+                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+                            Slog.d(TAG, sb.toString());
+                        }
+
+                        u.mUserCpuTime.addCountLocked(userTimeUs);
+                        u.mSystemCpuTime.addCountLocked(systemTimeUs);
+
+                        // Add the cpu speeds to this UID. These are used as a ratio
+                        // for computing the power this UID used.
+                        for (int i = 0; i < cpuSpeedSteps; i++) {
+                            if (u.mSpeedBins[i] == null) {
+                                u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase);
+                            }
+                            u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]);
+                        }
+                    }
+                });
+
+        if (DEBUG_ENERGY_CPU) {
+            Slog.d(TAG, "Reading cpu stats took " + (SystemClock.elapsedRealtime() - startTimeMs) +
+                    " ms");
+        }
+
+        if (mOnBatteryInternal && numWakelocks > 0) {
+            // Distribute a portion of the total cpu time to wakelock holders.
+            mTempTotalCpuUserTimeUs = (mTempTotalCpuUserTimeUs * (100 - wakelockWeight)) / 100;
+            mTempTotalCpuSystemTimeUs =
+                    (mTempTotalCpuSystemTimeUs * (100 - wakelockWeight)) / 100;
+
+            for (int i = 0; i < numPartialTimers; i++) {
+                final StopwatchTimer timer = mPartialTimers.get(i);
+
+                // The system does not share any blame, as it is usually holding the wakelock
+                // on behalf of an app.
+                if (timer.mInList && timer.mUid != null && timer.mUid.mUid != Process.SYSTEM_UID) {
+                    int userTimeUs = (int) (mTempTotalCpuUserTimeUs / numWakelocks);
+                    int systemTimeUs = (int) (mTempTotalCpuSystemTimeUs / numWakelocks);
+
+                    if (DEBUG_ENERGY_CPU) {
+                        StringBuilder sb = new StringBuilder();
+                        sb.append("  Distributing wakelock uid=").append(timer.mUid.mUid)
+                                .append(": u=");
+                        TimeUtils.formatDuration(userTimeUs / 1000, sb);
+                        sb.append(" s=");
+                        TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+                        Slog.d(TAG, sb.toString());
+                    }
+
+                    timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
+                    timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
+
+                    final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
+                    proc.addCpuTimeLocked(userTimeUs, systemTimeUs);
+
+                    mTempTotalCpuUserTimeUs -= userTimeUs;
+                    mTempTotalCpuSystemTimeUs -= systemTimeUs;
+                    numWakelocks--;
+                }
+            }
+
+            if (mTempTotalCpuUserTimeUs > 0 || mTempTotalCpuSystemTimeUs > 0) {
+                // Anything left over is given to the system.
+                if (DEBUG_ENERGY_CPU) {
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("  Distributing lost time to system: u=");
+                    TimeUtils.formatDuration(mTempTotalCpuUserTimeUs / 1000, sb);
+                    sb.append(" s=");
+                    TimeUtils.formatDuration(mTempTotalCpuSystemTimeUs / 1000, sb);
+                    Slog.d(TAG, sb.toString());
+                }
+
+                final Uid u = getUidStatsLocked(Process.SYSTEM_UID);
+                u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs);
+                u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs);
+
+                final Uid.Proc proc = u.getProcessStatsLocked("*lost*");
+                proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs,
+                        (int) mTempTotalCpuSystemTimeUs);
+            }
+        }
+
+        // See if there is a difference in wakelocks between this collection and the last
+        // collection.
+        if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
+            // No difference, so each timer is now considered for the next collection.
+            for (int i = 0; i < numPartialTimers; i++) {
+                mPartialTimers.get(i).mInList = true;
+            }
+        } else {
+            // The lists are different, meaning we added (or removed a timer) since the last
+            // collection.
+            final int numLastPartialTimers = mLastPartialTimers.size();
+            for (int i = 0; i < numLastPartialTimers; i++) {
+                mLastPartialTimers.get(i).mInList = false;
+            }
+            mLastPartialTimers.clear();
+
+            // Mark the current timers as gone through a collection.
+            for (int i = 0; i < numPartialTimers; i++) {
+                final StopwatchTimer timer = mPartialTimers.get(i);
+                timer.mInList = true;
+                mLastPartialTimers.add(timer);
+            }
+        }
     }
 
     boolean setChargingLocked(boolean charging) {
@@ -8157,6 +8246,12 @@
         }
     }
 
+    private void scheduleSyncExternalWifiStatsLocked(String reason) {
+        if (mExternalSync != null) {
+            mExternalSync.scheduleWifiSync(reason);
+        }
+    }
+
     // This should probably be exposed in the API, though it's not critical
     public static final int BATTERY_PLUGGED_NONE = 0;
 
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
index b236378..62926d1 100644
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
@@ -16,9 +16,11 @@
 package com.android.internal.os;
 
 import android.annotation.Nullable;
+import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseLongArray;
+import android.util.TimeUtils;
 
 import java.io.BufferedReader;
 import java.io.FileReader;
@@ -49,6 +51,7 @@
 
     private SparseLongArray mLastUserTimeUs = new SparseLongArray();
     private SparseLongArray mLastSystemTimeUs = new SparseLongArray();
+    private long mLastTimeRead = 0;
 
     /**
      * Reads the proc file, calling into the callback with a delta of time for each UID.
@@ -57,6 +60,7 @@
      *                 a fresh delta.
      */
     public void readDelta(@Nullable Callback callback) {
+        long now = SystemClock.elapsedRealtime();
         try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) {
             TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
             String line;
@@ -75,10 +79,32 @@
                         userTimeDeltaUs -= mLastUserTimeUs.valueAt(index);
                         systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index);
 
-                        if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0) {
-                            // The UID must have been removed from accounting, then added back.
-                            userTimeDeltaUs = userTimeUs;
-                            systemTimeDeltaUs = systemTimeUs;
+                        final long timeDiffMs = (now - mLastTimeRead) * 1000;
+                        if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 ||
+                                userTimeDeltaUs > timeDiffMs || systemTimeDeltaUs > timeDiffMs ) {
+                            StringBuilder sb = new StringBuilder("Malformed cpu data!\n");
+                            sb.append("Time between reads: ");
+                            TimeUtils.formatDuration(timeDiffMs, sb);
+                            sb.append("ms\n");
+                            sb.append("Previous times: u=");
+                            TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb);
+                            sb.append("ms s=");
+                            TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb);
+                            sb.append("ms\n");
+                            sb.append("Current times: u=");
+                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
+                            sb.append("ms s=");
+                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+                            sb.append("ms\n");
+                            sb.append("Delta for UID=").append(uid).append(": u=");
+                            TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb);
+                            sb.append("ms s=");
+                            TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb);
+                            sb.append("ms");
+                            Slog.wtf(TAG, sb.toString());
+
+                            userTimeDeltaUs = 0;
+                            systemTimeDeltaUs = 0;
                         }
                     }
 
@@ -92,6 +118,7 @@
         } catch (IOException e) {
             Slog.e(TAG, "Failed to read uid_cputime", e);
         }
+        mLastTimeRead = now;
     }
 
     /**
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 4f6d781..c97fdf4 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -41,8 +41,8 @@
     public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4;
     /** enable the JIT compiler */
     public static final int DEBUG_ENABLE_JIT         = 1 << 5;
-    /** Force generation of CFI code */
-    public static final int DEBUG_GENERATE_CFI       = 1 << 6;
+    /** Force generation of native debugging information. */
+    public static final int DEBUG_GENERATE_DEBUG_INFO = 1 << 6;
 
     /** No external storage should be mounted. */
     public static final int MOUNT_EXTERNAL_NONE = 0;
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 1a0345b..fa870b9 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -322,7 +322,7 @@
 
         /**
          * From --enable-debugger, --enable-checkjni, --enable-assert,
-         * --enable-safemode, --enable-jit, --generate-cfi and --enable-jni-logging.
+         * --enable-safemode, --enable-jit, --generate-debug-info and --enable-jni-logging.
          */
         int debugFlags;
 
@@ -434,8 +434,8 @@
                     debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
                 } else if (arg.equals("--enable-jit")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_JIT;
-                } else if (arg.equals("--generate-cfi")) {
-                    debugFlags |= Zygote.DEBUG_GENERATE_CFI;
+                } else if (arg.equals("--generate-debug-info")) {
+                    debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
                 } else if (arg.equals("--enable-jni-logging")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
                 } else if (arg.equals("--enable-assert")) {
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 66f6079..15ed5bd 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3223,12 +3223,11 @@
                 cb.onWindowFocusChanged(hasWindowFocus);
             }
 
-            if (mFloatingToolbar != null) {
-                if (hasWindowFocus) {
-                    mFloatingToolbar.show();
-                } else {
-                    mFloatingToolbar.dismiss();
-                }
+            if (mPrimaryActionMode != null) {
+                mPrimaryActionMode.onWindowFocusChanged(hasWindowFocus);
+            }
+            if (mFloatingActionMode != null) {
+                mFloatingActionMode.onWindowFocusChanged(hasWindowFocus);
             }
         }
 
@@ -3441,8 +3440,7 @@
             mFloatingActionMode = mode;
             mFloatingToolbar = new FloatingToolbar(mContext, PhoneWindow.this);
             ((FloatingActionMode) mFloatingActionMode).setFloatingToolbar(mFloatingToolbar);
-            mFloatingActionMode.invalidate();
-            mFloatingToolbar.show();
+            mFloatingActionMode.invalidate();  // Will show the floating toolbar if necessary.
             mFloatingActionModeOriginatingView.getViewTreeObserver()
                 .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
         }
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 9f99f62..0732add 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -64,5 +64,7 @@
      *        bar caused by this app transition in millis
      */
     void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration);
+
+    void showAssistDisclosure();
 }
 
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 62e724a..9d0636a 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -387,4 +387,26 @@
     public static <T> boolean contains(ArrayList<T> cur, T val) {
         return (cur != null) ? cur.contains(val) : false;
     }
+
+    /**
+     * Returns true if the two ArrayLists are equal with respect to the objects they contain.
+     * The objects must be in the same order and be reference equal (== not .equals()).
+     */
+    public static <T> boolean referenceEquals(ArrayList<T> a, ArrayList<T> b) {
+        if (a == b) {
+            return true;
+        }
+
+        final int sizeA = a.size();
+        final int sizeB = b.size();
+        if (a == null || b == null || sizeA != sizeB) {
+            return false;
+        }
+
+        boolean diff = false;
+        for (int i = 0; i < sizeA && !diff; i++) {
+            diff |= a.get(i) != b.get(i);
+        }
+        return !diff;
+    }
 }
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 784b256..863506b 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -197,6 +197,13 @@
     }
 
     @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        checkToolbarInitialized();
+        mFloatingToolbarVisibilityHelper.setWindowFocused(hasWindowFocus);
+        mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
+    }
+
+    @Override
     public void finish() {
         checkToolbarInitialized();
         reset();
@@ -237,6 +244,7 @@
     }
 
     private void reset() {
+        mFloatingToolbar.dismiss();
         mFloatingToolbarVisibilityHelper.deactivate();
         mOriginatingView.removeCallbacks(mMovingOff);
         mOriginatingView.removeCallbacks(mHideOff);
@@ -253,6 +261,7 @@
         private boolean mHideRequested;
         private boolean mMoving;
         private boolean mOutOfBounds;
+        private boolean mWindowFocused = true;
 
         private boolean mActive;
 
@@ -264,6 +273,7 @@
             mHideRequested = false;
             mMoving = false;
             mOutOfBounds = false;
+            mWindowFocused = true;
 
             mActive = true;
         }
@@ -285,12 +295,16 @@
             mOutOfBounds = outOfBounds;
         }
 
+        public void setWindowFocused(boolean windowFocused) {
+            mWindowFocused = windowFocused;
+        }
+
         public void updateToolbarVisibility() {
             if (!mActive) {
                 return;
             }
 
-            if (mHideRequested || mMoving || mOutOfBounds) {
+            if (mHideRequested || mMoving || mOutOfBounds || !mWindowFocused) {
                 mToolbar.hide();
             } else {
                 mToolbar.show();
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index e19b2b6..85ec29c 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -409,8 +409,8 @@
             }
             case DO_REPORT_FULLSCREEN_MODE: {
                 InputConnection ic = mInputConnection.get();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "showStatusIcon on inactive InputConnection");
+                if (ic == null) {
+                    Log.w(TAG, "reportFullscreenMode on inexistent InputConnection");
                     return;
                 }
                 ic.reportFullscreenMode(msg.arg1 == 1);
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 65f2f53f..523663c 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -546,25 +546,25 @@
         private void refreshCoordinatesAndOverflowDirection(Rect contentRect) {
             refreshViewPort();
 
-            int availableHeightAboveContent =
-                    contentRect.top - mViewPort.top - 2 * mMarginVertical;
-            int availableHeightBelowContent =
-                    mViewPort.bottom - contentRect.bottom - 2 * mMarginVertical;
-            int availableHeightThroughContent =
-                    mViewPort.bottom - contentRect.top + getToolbarHeightWithVerticalMargin();
-
             int x = contentRect.centerX() - getWidth() / 2;
             // Update x so that the toolbar isn't rendered behind the nav bar in landscape.
             x = Math.max(0, Math.min(x, mViewPort.right - getWidth()));
 
             int y;
+
+            int availableHeightAboveContent = contentRect.top - mViewPort.top;
+            int availableHeightBelowContent = mViewPort.bottom - contentRect.bottom;
+
             if (mOverflowPanel == null) {  // There is no overflow.
-                if (availableHeightAboveContent > getToolbarHeightWithVerticalMargin()) {
+                if (availableHeightAboveContent >= getToolbarHeightWithVerticalMargin()) {
                     // There is enough space at the top of the content.
                     y = contentRect.top - getToolbarHeightWithVerticalMargin();
-                } else if (availableHeightBelowContent > getToolbarHeightWithVerticalMargin()) {
+                } else if (availableHeightBelowContent >= getToolbarHeightWithVerticalMargin()) {
                     // There is enough space at the bottom of the content.
                     y = contentRect.bottom;
+                } else if (availableHeightBelowContent >= getEstimatedToolbarHeight(getContext())) {
+                    // Just enough space to fit the toolbar with no vertical margins.
+                    y = contentRect.bottom - mMarginVertical;
                 } else {
                     // Not enough space. Prefer to position as high as possible.
                     y = Math.max(
@@ -572,32 +572,47 @@
                             contentRect.top - getToolbarHeightWithVerticalMargin());
                 }
             } else {  // There is an overflow.
-                if (availableHeightAboveContent > mOverflowPanel.getMinimumHeight()) {
+                int margin = 2 * mMarginVertical;
+                int minimumOverflowHeightWithMargin = mOverflowPanel.getMinimumHeight() + margin;
+                int availableHeightThroughContentDown =
+                        mViewPort.bottom - contentRect.top + getToolbarHeightWithVerticalMargin();
+                int availableHeightThroughContentUp =
+                        contentRect.bottom - mViewPort.top + getToolbarHeightWithVerticalMargin();
+
+                if (availableHeightAboveContent >= minimumOverflowHeightWithMargin) {
                     // There is enough space at the top of the content rect for the overflow.
                     // Position above and open upwards.
-                    updateOverflowHeight(availableHeightAboveContent);
+                    updateOverflowHeight(availableHeightAboveContent - margin);
                     y = contentRect.top - getHeight();
                     mOverflowDirection = OVERFLOW_DIRECTION_UP;
-                } else if (availableHeightAboveContent > getToolbarHeightWithVerticalMargin()
-                        && availableHeightThroughContent > mOverflowPanel.getMinimumHeight()) {
+                } else if (availableHeightAboveContent >= getToolbarHeightWithVerticalMargin()
+                        && availableHeightThroughContentDown >= minimumOverflowHeightWithMargin) {
                     // There is enough space at the top of the content rect for the main panel
                     // but not the overflow.
                     // Position above but open downwards.
-                    updateOverflowHeight(availableHeightThroughContent);
+                    updateOverflowHeight(availableHeightThroughContentDown - margin);
                     y = contentRect.top - getToolbarHeightWithVerticalMargin();
                     mOverflowDirection = OVERFLOW_DIRECTION_DOWN;
-                } else if (availableHeightBelowContent > mOverflowPanel.getMinimumHeight()) {
+                } else if (availableHeightBelowContent >= minimumOverflowHeightWithMargin) {
                     // There is enough space at the bottom of the content rect for the overflow.
                     // Position below and open downwards.
-                    updateOverflowHeight(availableHeightBelowContent);
+                    updateOverflowHeight(availableHeightBelowContent - margin);
                     y = contentRect.bottom;
                     mOverflowDirection = OVERFLOW_DIRECTION_DOWN;
+                } else if (availableHeightBelowContent >= getToolbarHeightWithVerticalMargin()
+                        && mViewPort.height() >= minimumOverflowHeightWithMargin) {
+                    // There is enough space at the bottom of the content rect for the main panel
+                    // but not the overflow.
+                    // Position below but open upwards.
+                    updateOverflowHeight(availableHeightThroughContentUp - margin);
+                    y = contentRect.bottom + getToolbarHeightWithVerticalMargin() - getHeight();
+                    mOverflowDirection = OVERFLOW_DIRECTION_UP;
                 } else {
                     // Not enough space.
-                    // Position at the bottom of the view port and open upwards.
-                    updateOverflowHeight(mViewPort.height());
-                    y = mViewPort.bottom - getHeight();
-                    mOverflowDirection = OVERFLOW_DIRECTION_UP;
+                    // Position at the top of the view port and open downwards.
+                    updateOverflowHeight(mViewPort.height() - margin);
+                    y = mViewPort.top;
+                    mOverflowDirection = OVERFLOW_DIRECTION_DOWN;
                 }
                 mOverflowPanel.setOverflowDirection(mOverflowDirection);
             }
@@ -1422,7 +1437,6 @@
         PopupWindow popupWindow = new PopupWindow(popupContentHolder);
         popupWindow.setWindowLayoutType(
                 WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
-        popupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
         popupWindow.setAnimationStyle(0);
         popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
         content.setLayoutParams(new ViewGroup.LayoutParams(
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 7c2b28d..2c35a8b 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -876,16 +876,16 @@
                        "-Xzygote-max-boot-retry=");
 
     /*
-     * When running with debug.gencfi, add --include-cfi to the compiler options so that the boot
-     * image, if it is compiled on device, will include CFI info, as well as other compilations
-     * started by the runtime.
+     * When running with debug.generate-debug-info, add --generate-debug-info to
+     * the compiler options so that the boot image, if it is compiled on device,
+     * will include native debugging information.
      */
-    property_get("debug.gencfi", propBuf, "");
+    property_get("debug.generate-debug-info", propBuf, "");
     if (strcmp(propBuf, "true") == 0) {
         addOption("-Xcompiler-option");
-        addOption("--include-cfi");
+        addOption("--generate-debug-info");
         addOption("-Ximage-compiler-option");
-        addOption("--include-cfi");
+        addOption("--generate-debug-info");
     }
 
     initArgs.version = JNI_VERSION_1_4;
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7272ae3..424a0b7 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2031,10 +2031,8 @@
         string that's stored in 8-bit unpacked format) characters.-->
     <bool translatable="false" name="config_sms_decode_gsm_8bit_data">false</bool>
 
-    <!-- List of package names (ordered by preference) providing WebView implementations. -->
-    <string-array name="config_webViewPackageNames" translatable="false">
-      <item>com.android.webview</item>
-    </string-array>
+    <!-- Package name providing WebView implementation. -->
+    <string name="config_webViewPackageName" translatable="false">com.android.webview</string>
 
     <!-- If EMS is not supported, framework breaks down EMS into single segment SMS
          and adds page info " x/y". This config is used to set which carrier doesn't
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4160e0e..295251c 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2018,7 +2018,7 @@
   <java-symbol type="attr" name="actionModeWebSearchDrawable" />
   <java-symbol type="string" name="websearch" />
   <java-symbol type="drawable" name="ic_media_video_poster" />
-  <java-symbol type="array" name="config_webViewPackageNames" />
+  <java-symbol type="string" name="config_webViewPackageName" />
 
   <!-- From SubtitleView -->
   <java-symbol type="dimen" name="subtitle_corner_radius" />
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 9a834506..7b1169f 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -30,21 +30,22 @@
 
 
 
-sdk.linux_download=android-sdk_r24.3.2-linux.tgz
-sdk.linux_bytes=309138263
-sdk.linux_checksum=4a10e62c5d88fd6c2a69db12348cbe168228b98f
+sdk.linux_download=android-sdk_r24.3.3-linux.tgz
+sdk.linux_bytes=309109716
+sdk.linux_checksum=cd4cab76c2e3d926b3495c26ec56c831ba77d0d0
 
-sdk.mac_download=android-sdk_r24.3.2-macosx.zip
-sdk.mac_bytes=98329772
-sdk.mac_checksum=8609b92e26e9bd5796f771138c6b222b6c0cb474
+sdk.mac_download=android-sdk_r24.3.3-macosx.zip
+sdk.mac_bytes=98330824
+sdk.mac_checksum=41f0f3e76d6868018740e654aefb04fd765c357d
 
-sdk.win_download=android-sdk_r24.3.2-windows.zip
-sdk.win_bytes=187488291
-sdk.win_checksum=bcfe3c41ea7e33a29ad6f358adbdf977008be80a
+sdk.win_download=android-sdk_r24.3.3-windows.zip
+sdk.win_bytes=187480692
+sdk.win_checksum=b6a4899efbf20fc593042f1515446c6630ba502e
 
-sdk.win_installer=installer_r24.3.2-windows.exe
-sdk.win_installer_bytes=139471724
-sdk.win_installer_checksum=8f9d0ae9fdb37973ed62d6e93975ff375beb5542
+
+sdk.win_installer=installer_r24.3.3-windows.exe
+sdk.win_installer_bytes=139463749
+sdk.win_installer_checksum=bbdae40a7665e55b3cdb1fbae865986e6cd3df14
 
 
 
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 326fbe2..934b262 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -25,6 +25,36 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>SDK Tools, Revision 24.3.3</a> <em>(June 2015)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <dl>
+    <dt>Dependencies:</dt>
+
+    <dd>
+      <ul>
+        <li>Android SDK Platform-tools revision 19 or later.</li>
+      </ul>
+    </dd>
+
+    <dt>General Notes:</dt>
+    <dd>
+      <ul>
+        <li>Fixed issues with using Ant build tasks with the Eclipse ADT build structure. </li>
+        <li>Fixed the emulator boot problem on Mac OS X 10.8.5.</li>
+      </ul>
+    </dd>
+  </div>
+</div>
+
+
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>SDK Tools, Revision 24.3.2</a> <em>(June 2015)</em>
   </p>
 
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 9acfee2..ab61e2b 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -89,10 +89,23 @@
  * encrypted content, the samples returned from the extractor remain encrypted, they
  * are only decrypted when the samples are delivered to the decoder.
  * <p>
- * MediaDrm methods throw {@link java.lang.IllegalStateException}
- * when a method is called on a MediaDrm object that is in an invalid or inoperable
- * state. This is typically due to incorrect application API usage, but may also
- * be due to an unrecoverable failure in the DRM plugin or security hardware.
+ * MediaDrm methods throw {@link android.media.MediaDrm.MediaDrmStateException}
+ * when a method is called on a MediaDrm object that has had an unrecoverable failure 
+ * in the DRM plugin or security hardware. 
+ * {@link android.media.MediaDrm.MediaDrmStateException} extends 
+ * {@link java.lang.IllegalStateException} with the addition of a developer-readable 
+ * diagnostic information string associated with the exception.
+ * <p>
+ * In the event of a mediaserver process crash or restart while a MediaDrm object
+ * is active, MediaDrm methods may throw {@link android.media.MediaDrmResetException}.
+ * To recover, the app must release the MediaDrm object, then create and initialize
+ * a new one.
+ * <p>
+ * As {@link android.media.MediaDrmResetException} and 
+ * {@link android.media.MediaDrm.MediaDrmStateException} both extend 
+ * {@link java.lang.IllegalStateException}, they should be in an earlier catch() 
+ * block than {@link java.lang.IllegalStateException} if handled separately.
+ * <p>
  * <a name="Callbacks"></a>
  * <h3>Callbacks</h3>
  * <p>Applications should register for informational events in order
diff --git a/media/java/android/media/MediaDrmResetException.java b/media/java/android/media/MediaDrmResetException.java
new file mode 100644
index 0000000..3b2da1e
--- /dev/null
+++ b/media/java/android/media/MediaDrmResetException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2015 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 android.media;
+
+/**
+ * This exception is thrown when the MediaDrm instance has become unusable
+ * due to a restart of the mediaserver process.  To continue, the app must
+ * release the MediaDrm object, then create and initialize a new one.
+ */
+public class MediaDrmResetException extends IllegalStateException {
+    public MediaDrmResetException(String detailMessage) {
+        super(detailMessage);
+    }
+}
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index d456dc10..9ec0312 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -308,6 +308,10 @@
     } else if (err == ERROR_DRM_DEVICE_REVOKED) {
         jniThrowException(env, "android/media/DeniedByServerException", msg);
         return true;
+    } else if (err == DEAD_OBJECT) {
+        jniThrowException(env, "android/media/MediaDrmResetException",
+                "mediaserver died");
+        return true;
     } else if (err != OK) {
         String8 errbuf;
         if (drmMessage != NULL) {
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index fdc586b..aba4bbe 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -472,6 +472,8 @@
 
     if (lpJniStorage) {
         ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
+        env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioEffect_class);
+        env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioEffect_ref);
         delete lpJniStorage;
     }
 }
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 6098b4a..0557019 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -450,6 +450,8 @@
 
     if (lpJniStorage) {
         ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
+        env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_class);
+        env->DeleteGlobalRef(lpJniStorage->mCallbackData.visualizer_ref);
         delete lpJniStorage;
     }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index aa99a7b..0c6837f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -216,6 +216,19 @@
         return mCallback;
     }
 
+    @Override
+    public void showPromptReason(int reason) {
+        if (reason != PROMPT_REASON_NONE) {
+            int promtReasonStringRes = getPromtReasonStringRes(reason);
+            if (promtReasonStringRes != 0) {
+                mSecurityMessageDisplay.setMessage(promtReasonStringRes,
+                        true /* important */);
+            }
+        }
+    }
+
+    protected abstract int getPromtReasonStringRes(int reason);
+
     // Cause a VIRTUAL_KEY vibration
     public void doHapticKeyClick() {
         if (mEnableHaptics) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index cd4b24a..ff4e815 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -160,6 +160,17 @@
     }
 
     /**
+     * Show a string explaining why the security view needs to be solved.
+     *
+     * @param reason a flag indicating which string should be shown, see
+     *               {@link KeyguardSecurityView#PROMPT_REASON_NONE}
+     *               and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
+     */
+    public void showPromptReason(int reason) {
+        mSecurityContainer.showPromptReason(reason);
+    }
+
+    /**
      *  Dismisses the keyguard by going to the next screen or making it gone.
      *
      *  @return True if the keyguard is done.
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
index c9ad728..2db87b3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
@@ -111,6 +111,16 @@
     }
 
     @Override
+    protected int getPromtReasonStringRes(int reason) {
+        switch (reason) {
+            case PROMPT_REASON_RESTART:
+                return R.string.kg_prompt_reason_restart_password;
+            default:
+                return 0;
+        }
+    }
+
+    @Override
     public void onPause() {
         super.onPause();
         mImm.hideSoftInputFromWindow(getWindowToken(), 0);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 1bd0bb4..59a8ad5 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -85,10 +85,9 @@
         }
     };
     private Rect mTempRect = new Rect();
-    private SecurityMessageDisplay mSecurityMessageDisplay;
+    private KeyguardMessageArea mSecurityMessageDisplay;
     private View mEcaView;
     private ViewGroup mContainer;
-    private KeyguardMessageArea mHelpMessage;
     private int mDisappearYTranslation;
 
     enum FooterMode {
@@ -141,10 +140,10 @@
         // vibrate mode will be the same for the life of this screen
         mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
 
-        mSecurityMessageDisplay = KeyguardMessageArea.findSecurityMessageDisplay(this);
+        mSecurityMessageDisplay =
+                (KeyguardMessageArea) KeyguardMessageArea.findSecurityMessageDisplay(this);
         mEcaView = findViewById(R.id.keyguard_selector_fade_container);
         mContainer = (ViewGroup) findViewById(R.id.container);
-        mHelpMessage = (KeyguardMessageArea) findViewById(R.id.keyguard_message_area);
 
         EmergencyButton button = (EmergencyButton) findViewById(R.id.emergency_call_button);
         if (button != null) {
@@ -320,6 +319,17 @@
     }
 
     @Override
+    public void showPromptReason(int reason) {
+        switch (reason) {
+            case PROMPT_REASON_RESTART:
+                mSecurityMessageDisplay.setMessage(R.string.kg_prompt_reason_restart_pattern,
+                        true /* important */);
+                break;
+            default:
+        }
+    }
+
+    @Override
     public void startAppearAnimation() {
         enableClipping(false);
         setAlpha(1f);
@@ -337,8 +347,8 @@
                     }
                 },
                 this);
-        if (!TextUtils.isEmpty(mHelpMessage.getText())) {
-            mAppearAnimationUtils.createAnimation(mHelpMessage, 0,
+        if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) {
+            mAppearAnimationUtils.createAnimation(mSecurityMessageDisplay, 0,
                     AppearAnimationUtils.DEFAULT_APPEAR_DURATION,
                     mAppearAnimationUtils.getStartTranslation(),
                     true /* appearing */,
@@ -366,8 +376,8 @@
                         }
                     }
                 }, KeyguardPatternView.this);
-        if (!TextUtils.isEmpty(mHelpMessage.getText())) {
-            mDisappearAnimationUtils.createAnimation(mHelpMessage, 0,
+        if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) {
+            mDisappearAnimationUtils.createAnimation(mSecurityMessageDisplay, 0,
                     200,
                     - mDisappearAnimationUtils.getStartTranslation() * 3,
                     false /* appearing */,
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 23834a3..07947b1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -93,6 +93,16 @@
         return super.onKeyDown(keyCode, event);
     }
 
+    @Override
+    protected int getPromtReasonStringRes(int reason) {
+        switch (reason) {
+            case PROMPT_REASON_RESTART:
+                return R.string.kg_prompt_reason_restart_pin;
+            default:
+                return 0;
+        }
+    }
+
     private void performClick(View view) {
         view.performClick();
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index d17b25a..f529ac0 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -509,6 +509,13 @@
     }
 
     @Override
+    public void showPromptReason(int reason) {
+        if (mCurrentSecuritySelection != SecurityMode.None) {
+            getSecurityView(mCurrentSecuritySelection).showPromptReason(reason);
+        }
+    }
+
+    @Override
     public void showUsabilityHint() {
         mSecurityViewFlipper.showUsabilityHint();
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
index 5b50236..5658a74 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
@@ -21,6 +21,9 @@
     static public final int SCREEN_ON = 1;
     static public final int VIEW_REVEALED = 2;
 
+    int PROMPT_REASON_NONE = 0;
+    int PROMPT_REASON_RESTART = 1;
+
     /**
      * Interface back to keyguard to tell it when security
      * @param callback
@@ -66,6 +69,14 @@
     KeyguardSecurityCallback getCallback();
 
     /**
+     * Show a string explaining why the security view needs to be solved.
+     *
+     * @param reason a flag indicating which string should be shown, see {@link #PROMPT_REASON_NONE}
+     *               and {@link #PROMPT_REASON_RESTART}
+     */
+    void showPromptReason(int reason);
+
+    /**
      * Instruct the view to show usability hints, if any.
      *
      */
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 54467f3..a0ff21b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -131,6 +131,14 @@
     }
 
     @Override
+    public void showPromptReason(int reason) {
+        KeyguardSecurityView ksv = getSecurityView();
+        if (ksv != null) {
+            ksv.showPromptReason(reason);
+        }
+    }
+
+    @Override
     public void showUsabilityHint() {
         KeyguardSecurityView ksv = getSecurityView();
         if (ksv != null) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index f4acff8..aeac912 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -95,6 +95,12 @@
         }
     }
 
+    @Override
+    protected int getPromtReasonStringRes(int reason) {
+        // No message on SIM Pin
+        return 0;
+    }
+
     private String getPinPasswordErrorMessage(int attemptsRemaining) {
         String displayMessage;
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
index b85d966..af88239 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
@@ -140,6 +140,12 @@
         }
     }
 
+    @Override
+    protected int getPromtReasonStringRes(int reason) {
+        // No message on SIM Puk
+        return 0;
+    }
+
     private String getPukPasswordErrorMessage(int attemptsRemaining) {
         String displayMessage;
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 273f166..022338d 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -804,8 +804,7 @@
     private void startListeningForFingerprint() {
         if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
         int userId = ActivityManager.getCurrentUser();
-        if (mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId)
-                && mFpm.getEnrolledFingerprints(userId).size() > 0) {
+        if (isUnlockWithFingerPrintPossible(userId)) {
             if (mFingerprintCancelSignal != null) {
                 mFingerprintCancelSignal.cancel();
             }
@@ -815,6 +814,11 @@
         }
     }
 
+    public boolean isUnlockWithFingerPrintPossible(int userId) {
+        return mFpm != null && mFpm.isHardwareDetected() && !isFingerprintDisabled(userId)
+                && mFpm.getEnrolledFingerprints(userId).size() > 0;
+    }
+
     private void stopListeningForFingerprint() {
         if (DEBUG) Log.v(TAG, "stopListeningForFingerprint()");
         if (isFingerprintDetectionRunning()) {
diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
index f5c809a..ff463c6 100644
--- a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
@@ -81,4 +81,12 @@
      * @return true if the screen is on
      */
     boolean isScreenOn();
+
+    /**
+     * @return one of the reasons why the bouncer needs to be shown right now and the user can't use
+     *         his normal unlock method like fingerprint or trust agents. See
+     *         {@link KeyguardSecurityView#PROMPT_REASON_NONE}
+     *         and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}.
+     */
+    int getBouncerPromptReason();
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index b0429ef..249eaa5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -808,7 +808,7 @@
             // The pairing dialog now warns of phone-book access for paired devices.
             // No separate prompt is displayed after pairing.
             if (getPhonebookPermissionChoice() == CachedBluetoothDevice.ACCESS_UNKNOWN) {
-                setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_ALLOWED);
+                setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_REJECTED);
             }
         }
     }
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index 13747ed..0c84fa1 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -27,6 +27,7 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.FileUtils;
@@ -77,21 +78,12 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
+        final Configuration conf = context.getResources().getConfiguration();
         final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
         final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT);
 
-        // Files are kept on private storage, so turn into Uris that we can
-        // grant temporary permissions for.
-        final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
-        final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
-
-        boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt");
-        if (!isPlainText) {
-            // Already zipped, send it right away.
-            sendBugreportNotification(context, bugreportFile, screenshotFile);
-        } else {
-            // Asynchronously zip the file first, then send it.
-            sendZippedBugreportNotification(context, bugreportFile, screenshotFile);
+        if ((conf.uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_WATCH) {
+            triggerLocalNotification(context, bugreportFile, screenshotFile);
         }
 
         // Clean up older bugreports in background
@@ -107,6 +99,29 @@
         }.execute();
     }
 
+    /**
+     * Responsible for triggering a notification that allows the user to start a
+     * "share" intent with the bug report. On watches we have other methods to allow the user to
+     * start this intent (usually by triggering it on another connected device); we don't need to
+     * display the notification in this case.
+     */
+    private void triggerLocalNotification(final Context context, final File bugreportFile,
+            final File screenshotFile) {
+        // Files are kept on private storage, so turn into Uris that we can
+        // grant temporary permissions for.
+        final Uri bugreportUri = FileProvider.getUriForFile(context, AUTHORITY, bugreportFile);
+        final Uri screenshotUri = FileProvider.getUriForFile(context, AUTHORITY, screenshotFile);
+
+        boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt");
+        if (!isPlainText) {
+            // Already zipped, send it right away.
+            sendBugreportNotification(context, bugreportFile, screenshotFile);
+        } else {
+            // Asynchronously zip the file first, then send it.
+            sendZippedBugreportNotification(context, bugreportFile, screenshotFile);
+        }
+    }
+
     private static Intent buildWarningIntent(Context context, Intent sendIntent) {
         final Intent intent = new Intent(context, BugreportWarningActivity.class);
         intent.putExtra(Intent.EXTRA_INTENT, sendIntent);
diff --git a/packages/SystemUI/res/drawable/managed_profile_toast_background.xml b/packages/SystemUI/res/drawable/managed_profile_toast_background.xml
deleted file mode 100644
index 5c77b9a..0000000
--- a/packages/SystemUI/res/drawable/managed_profile_toast_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2015 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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <corners android:radius="2dp" />
-    <solid android:color="@color/managed_profile_toast_background" />
-</shape>
diff --git a/packages/SystemUI/res/layout/managed_profile_toast.xml b/packages/SystemUI/res/layout/managed_profile_toast.xml
deleted file mode 100644
index 5a01ca7..0000000
--- a/packages/SystemUI/res/layout/managed_profile_toast.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2015 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:paddingTop="16dp"
-        android:paddingBottom="16dp"
-        android:paddingLeft="32dp"
-        android:paddingRight="32dp"
-        android:background="@drawable/managed_profile_toast_background">
-    <ImageView
-            android:layout_width="32dp"
-            android:layout_height="32dp"
-            android:layout_gravity="center_horizontal"
-            android:layout_marginBottom="16dp"
-            android:src="@drawable/stat_sys_managed_profile_status"/>
-    <TextView android:text="@string/managed_profile_foreground_toast"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textColor="@android:color/white"
-            android:textSize="14sp"
-            android:layout_gravity="center_horizontal" />
-</LinearLayout>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 9a96939..0dcbe88 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -143,6 +143,4 @@
     <color name="volume_icon_color">#ffffffff</color>
     <color name="volume_settings_icon_color">#7fffffff</color>
     <color name="volume_slider_inactive">#FFB0BEC5</color><!-- blue grey 200 -->
-
-    <color name="managed_profile_toast_background">#E5000000</color><!-- 90% black -->
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b0e71f9..869b03a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -575,4 +575,13 @@
 
     <!-- Standard image button size for volume dialog buttons -->
     <dimen name="volume_button_size">48dp</dimen>
+
+    <!-- Padding between icon and text for managed profile toast -->
+    <dimen name="managed_profile_toast_padding">4dp</dimen>
+
+    <!-- Thickness of the assist disclosure beams -->
+    <dimen name="assist_disclosure_thickness">4dp</dimen>
+
+    <!-- Thickness of the shadows of the assist disclosure beams -->
+    <dimen name="assist_disclosure_shadow_thickness">1.5dp</dimen>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
new file mode 100644
index 0000000..234a699
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2015 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.assist;
+
+import com.android.systemui.R;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.os.Handler;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.animation.AnimationUtils;
+
+/**
+ * Visually discloses that contextual data was provided to an assistant.
+ */
+public class AssistDisclosure {
+    private final Context mContext;
+    private final WindowManager mWm;
+    private final Handler mHandler;
+
+    private AssistDisclosureView mView;
+    private boolean mViewAdded;
+
+    public AssistDisclosure(Context context, Handler handler) {
+        mContext = context;
+        mHandler = handler;
+        mWm = mContext.getSystemService(WindowManager.class);
+    }
+
+    public void postShow() {
+        mHandler.removeCallbacks(mShowRunnable);
+        mHandler.post(mShowRunnable);
+    }
+
+    private void show() {
+        if (mView == null) {
+            mView = new AssistDisclosureView(mContext);
+        }
+        if (!mViewAdded) {
+            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                    WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
+                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                            | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
+                            | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                            | WindowManager.LayoutParams.FLAG_FULLSCREEN
+                            | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
+                    PixelFormat.TRANSLUCENT);
+            lp.setTitle("AssistDisclosure");
+
+            mWm.addView(mView, lp);
+            mViewAdded = true;
+        }
+    }
+
+    private void hide() {
+        if (mViewAdded) {
+            mWm.removeView(mView);
+            mViewAdded = false;
+        }
+    }
+
+    private Runnable mShowRunnable = new Runnable() {
+        @Override
+        public void run() {
+            show();
+        }
+    };
+
+    private class AssistDisclosureView extends View
+            implements ValueAnimator.AnimatorUpdateListener {
+
+        public static final int TRACING_ANIMATION_DURATION = 300;
+        public static final int ALPHA_ANIMATION_DURATION = 200;
+
+        private float mThickness;
+        private float mShadowThickness;
+        private final Paint mPaint = new Paint();
+        private final Paint mShadowPaint = new Paint();
+
+        private final ValueAnimator mTracingAnimator;
+        private final ValueAnimator mAlphaAnimator;
+        private final AnimatorSet mAnimator;
+
+        private float mTracingProgress = 0;
+        private int mAlpha = 255;
+
+        public AssistDisclosureView(Context context) {
+            super(context);
+
+            mTracingAnimator = ValueAnimator.ofFloat(0, 1).setDuration(TRACING_ANIMATION_DURATION);
+            mTracingAnimator.addUpdateListener(this);
+            mTracingAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext,
+                    android.R.interpolator.fast_out_slow_in));
+            mAlphaAnimator = ValueAnimator.ofInt(255, 0).setDuration(ALPHA_ANIMATION_DURATION);
+            mAlphaAnimator.addUpdateListener(this);
+            mAlphaAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext,
+                    android.R.interpolator.fast_out_linear_in));
+            mAnimator = new AnimatorSet();
+            mAnimator.play(mTracingAnimator).before(mAlphaAnimator);
+            mAnimator.addListener(new AnimatorListenerAdapter() {
+                boolean mCancelled;
+
+                @Override
+                public void onAnimationStart(Animator animation) {
+                    mCancelled = false;
+                }
+
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    mCancelled = true;
+                }
+
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    if (!mCancelled) {
+                        hide();
+                    }
+                }
+            });
+
+            PorterDuffXfermode srcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
+            mPaint.setColor(Color.WHITE);
+            mPaint.setXfermode(srcMode);
+            mShadowPaint.setColor(Color.DKGRAY);
+            mShadowPaint.setXfermode(srcMode);
+
+            mThickness = getResources().getDimension(R.dimen.assist_disclosure_thickness);
+            mShadowThickness = getResources().getDimension(
+                    R.dimen.assist_disclosure_shadow_thickness);
+        }
+
+        @Override
+        protected void onAttachedToWindow() {
+            super.onAttachedToWindow();
+
+            startAnimation();
+        }
+
+        @Override
+        protected void onDetachedFromWindow() {
+            super.onDetachedFromWindow();
+
+            mAnimator.cancel();
+
+            mTracingProgress = 0;
+            mAlpha = 255;
+        }
+
+        private void startAnimation() {
+            mAnimator.cancel();
+            mAnimator.start();
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            mPaint.setAlpha(mAlpha);
+            mShadowPaint.setAlpha(mAlpha / 4);
+
+            drawGeometry(canvas, mShadowPaint, mShadowThickness);
+            drawGeometry(canvas, mPaint, 0);
+        }
+
+        private void drawGeometry(Canvas canvas, Paint paint, float padding) {
+            final int width = getWidth();
+            final int height = getHeight();
+            float thickness = mThickness;
+            final float pixelProgress = mTracingProgress * (width + height - 2 * thickness);
+
+            float bottomProgress = Math.min(pixelProgress, width / 2f);
+            if (bottomProgress > 0) {
+                drawBeam(canvas,
+                        width / 2f - bottomProgress,
+                        height - thickness,
+                        width / 2f + bottomProgress,
+                        height, paint, padding);
+            }
+
+            float sideProgress = Math.min(pixelProgress - bottomProgress, height - thickness);
+            if (sideProgress > 0) {
+                drawBeam(canvas,
+                        0,
+                        (height - thickness) - sideProgress,
+                        thickness,
+                        height - thickness, paint, padding);
+                drawBeam(canvas,
+                        width - thickness,
+                        (height - thickness) - sideProgress,
+                        width,
+                        height - thickness, paint, padding);
+            }
+
+            float topProgress = Math.min(pixelProgress - bottomProgress - sideProgress,
+                    width / 2 - thickness);
+            if (sideProgress > 0 && topProgress > 0) {
+                drawBeam(canvas,
+                        thickness,
+                        0,
+                        thickness + topProgress,
+                        thickness, paint, padding);
+                drawBeam(canvas,
+                        (width - thickness) - topProgress,
+                        0,
+                        width - thickness,
+                        thickness, paint, padding);
+            }
+        }
+
+        private void drawBeam(Canvas canvas, float left, float top, float right, float bottom,
+                Paint paint, float padding) {
+            canvas.drawRect(left - padding,
+                    top - padding,
+                    right + padding,
+                    bottom + padding,
+                    paint);
+        }
+
+        @Override
+        public void onAnimationUpdate(ValueAnimator animation) {
+            if (animation == mAlphaAnimator) {
+                mAlpha = (int) mAlphaAnimator.getAnimatedValue();
+            } else if (animation == mTracingAnimator) {
+                mTracingProgress = (float) mTracingAnimator.getAnimatedValue();
+            }
+            invalidate();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 445ecb6..674356b 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -55,6 +55,8 @@
 
     private final Context mContext;
     private final WindowManager mWindowManager;
+    private final AssistDisclosure mAssistDisclosure;
+
     private AssistOrbContainer mView;
     private final PhoneStatusBar mBar;
     private final AssistUtils mAssistUtils;
@@ -100,6 +102,7 @@
                 Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), false,
                 mAssistSettingsObserver);
         mAssistSettingsObserver.onChange(false);
+        mAssistDisclosure = new AssistDisclosure(context, new Handler());
     }
 
     public void onConfigurationChanged() {
@@ -187,8 +190,11 @@
         mBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL |
                 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL);
 
+        boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
+
         final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
+                .getAssistIntent(mContext, structureEnabled, UserHandle.USER_CURRENT);
         if (intent == null) {
             return;
         }
@@ -196,6 +202,10 @@
             intent.setComponent(mAssistComponent);
         }
 
+        if (structureEnabled) {
+            showDisclosure();
+        }
+
         try {
             final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
                     R.anim.search_launch_enter, R.anim.search_launch_exit);
@@ -297,4 +307,8 @@
         pw.println("AssistManager state:");
         pw.print("  mAssistComponent="); pw.println(mAssistComponent);
     }
+
+    public void showDisclosure() {
+        mAssistDisclosure.postShow();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c06b34f..80761d8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -62,6 +62,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardConstants;
 import com.android.keyguard.KeyguardDisplayManager;
+import com.android.keyguard.KeyguardSecurityView;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.ViewMediatorCallback;
@@ -526,6 +527,17 @@
         public boolean isScreenOn() {
             return mDeviceInteractive;
         }
+
+        @Override
+        public int getBouncerPromptReason() {
+            int currentUser = ActivityManager.getCurrentUser();
+            if ((mUpdateMonitor.getUserTrustIsManaged(currentUser)
+                    || mUpdateMonitor.isUnlockWithFingerPrintPossible(currentUser))
+                    && !mTrustManager.hasUserAuthenticatedSinceBoot(currentUser)) {
+                return KeyguardSecurityView.PROMPT_REASON_RESTART;
+            }
+            return KeyguardSecurityView.PROMPT_REASON_NONE;
+        }
     };
 
     public void userActivity() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 9761cd1..4b1453d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -390,7 +390,7 @@
             mDetailSettingsButton.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View v) {
-                    mHost.startSettingsActivity(settingsIntent);
+                    mHost.startActivityDismissingKeyguard(settingsIntent);
                 }
             });
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 72bb136..38fade2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -306,7 +306,7 @@
     }
 
     public interface Host {
-        void startSettingsActivity(Intent intent);
+        void startActivityDismissingKeyguard(Intent intent);
         void warn(String message, Throwable t);
         void collapsePanels();
         Looper getLooper();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index a9e8b38..07406b9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -82,7 +82,7 @@
         if (mDataController.isMobileDataSupported()) {
             showDetail(true);
         } else {
-            mHost.startSettingsActivity(CELLULAR_SETTINGS);
+            mHost.startActivityDismissingKeyguard(CELLULAR_SETTINGS);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index f97f519..1b74eb6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -263,7 +263,7 @@
     private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() {
         @Override
         public void onPrioritySettings() {
-            mHost.startSettingsActivity(ZEN_PRIORITY_SETTINGS);
+            mHost.startActivityDismissingKeyguard(ZEN_PRIORITY_SETTINGS);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 19f4df6..f7f7acb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -96,7 +96,11 @@
     private void sendIntent(String type, PendingIntent pi, String uri) {
         try {
             if (pi != null) {
-                pi.send();
+                if (pi.isActivity()) {
+                    getHost().startActivityDismissingKeyguard(pi.getIntent());
+                } else {
+                    pi.send();
+                }
             } else if (uri != null) {
                 final Intent intent = Intent.parseUri(uri, Intent.URI_INTENT_SCHEME);
                 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 9bc5b75..c33ef7c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -104,7 +104,7 @@
     @Override
     protected void handleSecondaryClick() {
         if (!mWifiController.canConfigWifi()) {
-            mHost.startSettingsActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
+            mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_WIFI_SETTINGS));
             return;
         }
         if (!mState.enabled) {
@@ -290,7 +290,7 @@
 
         @Override
         public void onSettingsActivityTriggered(Intent settingsIntent) {
-            mHost.startSettingsActivity(settingsIntent);
+            mHost.startActivityDismissingKeyguard(settingsIntent);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index a496548..295fdc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -393,13 +393,16 @@
                 if (recentTask != null && recentTask.size() > 0) {
                     UserInfo user = mUserManager.getUserInfo(recentTask.get(0).userId);
                     if (user != null && user.isManagedProfile()) {
-                        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
-                                Context.LAYOUT_INFLATER_SERVICE);
-                        View layout = inflater.inflate(R.layout.managed_profile_toast, null);
-                        Toast toast = new Toast(mContext);
-                        toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
-                        toast.setDuration(Toast.LENGTH_SHORT);
-                        toast.setView(layout);
+                        Toast toast = Toast.makeText(mContext,
+                                R.string.managed_profile_foreground_toast,
+                                Toast.LENGTH_SHORT);
+                        TextView text = (TextView) toast.getView().findViewById(
+                                android.R.id.message);
+                        text.setCompoundDrawablesRelativeWithIntrinsicBounds(
+                                R.drawable.stat_sys_managed_profile_status, 0, 0, 0);
+                        int paddingPx = mContext.getResources().getDimensionPixelSize(
+                                R.dimen.managed_profile_toast_padding);
+                        text.setCompoundDrawablePadding(paddingPx);
                         toast.show();
                     }
                 }
@@ -2098,4 +2101,11 @@
         }
         return mStatusBarKeyguardViewManager.isSecure();
     }
+
+    @Override
+    public void showAssistDisclosure() {
+        if (mAssistManager != null) {
+            mAssistManager.showDisclosure();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 80fdd28..0deff08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -61,6 +61,7 @@
     private static final int MSG_APP_TRANSITION_PENDING     = 19 << MSG_SHIFT;
     private static final int MSG_APP_TRANSITION_CANCELLED   = 20 << MSG_SHIFT;
     private static final int MSG_APP_TRANSITION_STARTING    = 21 << MSG_SHIFT;
+    private static final int MSG_ASSIST_DISCLOSURE          = 22 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -104,6 +105,7 @@
         public void appTransitionPending();
         public void appTransitionCancelled();
         public void appTransitionStarting(long startTime, long duration);
+        public void showAssistDisclosure();
     }
 
     public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -274,6 +276,13 @@
         }
     }
 
+    public void showAssistDisclosure() {
+        synchronized (mList) {
+            mHandler.removeMessages(MSG_ASSIST_DISCLOSURE);
+            mHandler.obtainMessage(MSG_ASSIST_DISCLOSURE).sendToTarget();
+        }
+    }
+
     private final class H extends Handler {
         public void handleMessage(Message msg) {
             final int what = msg.what & MSG_MASK;
@@ -366,6 +375,9 @@
                     Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
                     mCallbacks.appTransitionStarting(data.first, data.second);
                     break;
+                case MSG_ASSIST_DISCLOSURE:
+                    mCallbacks.showAssistDisclosure();
+                    break;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 3737d05..a3bb129 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -26,6 +26,7 @@
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardSecurityView;
 import com.android.keyguard.R;
 import com.android.keyguard.ViewMediatorCallback;
 
@@ -46,6 +47,7 @@
     private ViewGroup mRoot;
     private boolean mShowingSoon;
     private Choreographer mChoreographer = Choreographer.getInstance();
+    private int mBouncerPromptReason;
 
     public KeyguardBouncer(Context context, ViewMediatorCallback callback,
             LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
@@ -68,6 +70,8 @@
             return;
         }
 
+        mBouncerPromptReason = mCallback.getBouncerPromptReason();
+
         // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole
         // Keyguard. If we need to authenticate, show the bouncer.
         if (!mKeyguardView.dismiss()) {
@@ -84,12 +88,24 @@
         public void run() {
             mRoot.setVisibility(View.VISIBLE);
             mKeyguardView.onResume();
+            showPromptReason(mBouncerPromptReason);
             mKeyguardView.startAppearAnimation();
             mShowingSoon = false;
             mKeyguardView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         }
     };
 
+    /**
+     * Show a string explaining why the security view needs to be solved.
+     *
+     * @param reason a flag indicating which string should be shown, see
+     *               {@link KeyguardSecurityView#PROMPT_REASON_NONE}
+     *               and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
+     */
+    public void showPromptReason(int reason) {
+        mKeyguardView.showPromptReason(reason);
+    }
+
     private void cancelShowRunnable() {
         mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mShowRunnable, null);
         mShowingSoon = false;
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 cd90d27..ade40e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3101,16 +3101,16 @@
                 || (mDisabled1 & StatusBarManager.DISABLE_SEARCH) != 0;
     }
 
-    public void postStartSettingsActivity(final Intent intent, int delay) {
+    public void postStartActivityDismissingKeyguard(final Intent intent, int delay) {
         mHandler.postDelayed(new Runnable() {
             @Override
             public void run() {
-                handleStartSettingsActivity(intent, true /*onlyProvisioned*/);
+                handleStartActivityDismissingKeyguard(intent, true /*onlyProvisioned*/);
             }
         }, delay);
     }
 
-    private void handleStartSettingsActivity(Intent intent, boolean onlyProvisioned) {
+    private void handleStartActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned) {
         startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 25a93dd..12434ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -129,8 +129,8 @@
     }
 
     @Override
-    public void startSettingsActivity(final Intent intent) {
-        mStatusBar.postStartSettingsActivity(intent, 0);
+    public void startActivityDismissingKeyguard(final Intent intent) {
+        mStatusBar.postStartActivityDismissingKeyguard(intent, 0);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 3cc9297..daa84ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -154,6 +154,12 @@
     }
 
     private void updateConnected() {
+        // Make sure our connection state is up to date.
+        int state = mLocalBluetoothManager.getBluetoothAdapter().getConnectionState();
+        if (state != mConnectionState) {
+            mConnectionState = state;
+            mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
+        }
         if (mLastDevice != null && mLastDevice.isConnected()) {
             // Our current device is still valid.
             return;
@@ -203,9 +209,9 @@
 
     @Override
     public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
-        mConnectionState = state;
         mLastDevice = cachedDevice;
         updateConnected();
+        mConnectionState = state;
         mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
     }
 
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 8dd087a..82b334a 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -45,6 +45,7 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
@@ -487,7 +488,7 @@
                     mLocalPowerManager.setDeviceIdleMode(true);
                     try {
                         mNetworkPolicyManager.setDeviceIdleMode(true);
-                        mBatteryStats.noteDeviceIdleMode(true, false, false);
+                        mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());
                     } catch (RemoteException e) {
                     }
                     getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
@@ -496,18 +497,19 @@
                     mLocalPowerManager.setDeviceIdleMode(false);
                     try {
                         mNetworkPolicyManager.setDeviceIdleMode(false);
-                        mBatteryStats.noteDeviceIdleMode(false, false, false);
+                        mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid());
                     } catch (RemoteException e) {
                     }
                     getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
                 } break;
                 case MSG_REPORT_ACTIVE: {
-                    boolean fromMotion = msg.arg1 != 0;
+                    String activeReason = (String)msg.obj;
+                    int activeUid = msg.arg1;
                     boolean needBroadcast = msg.arg2 != 0;
                     mLocalPowerManager.setDeviceIdleMode(false);
                     try {
                         mNetworkPolicyManager.setDeviceIdleMode(false);
-                        mBatteryStats.noteDeviceIdleMode(false, !fromMotion, fromMotion);
+                        mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);
                     } catch (RemoteException e) {
                     }
                     if (needBroadcast) {
@@ -578,6 +580,12 @@
             }
         }
 
+        @Override public void exitIdle(String reason) {
+            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+                    null);
+            exitIdleInternal(reason);
+        }
+
         @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             DeviceIdleController.this.dump(fd, pw, args);
         }
@@ -818,6 +826,12 @@
         }
     }
 
+    public void exitIdleInternal(String reason) {
+        synchronized (this) {
+            becomeActiveLocked(reason, Binder.getCallingUid());
+        }
+    }
+
     void updateDisplayLocked() {
         mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
         // We consider any situation where the display is showing something to be it on,
@@ -830,7 +844,7 @@
             becomeInactiveIfAppropriateLocked();
         } else if (screenOn) {
             mScreenOn = true;
-            becomeActiveLocked("screen");
+            becomeActiveLocked("screen", Process.myUid());
         }
     }
 
@@ -841,21 +855,21 @@
             becomeInactiveIfAppropriateLocked();
         } else if (charging) {
             mCharging = charging;
-            becomeActiveLocked("charging");
+            becomeActiveLocked("charging", Process.myUid());
         }
     }
 
-    void scheduleReportActiveLocked(boolean fromMotion) {
-        Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, fromMotion ? 1 : 0,
-                mState == STATE_IDLE ? 1 : 0);
+    void scheduleReportActiveLocked(String activeReason, int activeUid) {
+        Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
+                mState == STATE_IDLE ? 1 : 0, activeReason);
         mHandler.sendMessage(msg);
     }
 
-    void becomeActiveLocked(String reason) {
-        if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + reason);
+    void becomeActiveLocked(String activeReason, int activeUid) {
+        if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
         if (mState != STATE_ACTIVE) {
-            EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason);
-            scheduleReportActiveLocked(false);
+            EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
+            scheduleReportActiveLocked(activeReason, activeUid);
             mState = STATE_ACTIVE;
             mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
             mNextIdlePendingDelay = 0;
@@ -896,7 +910,7 @@
         if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
             // Whoops, there is an upcoming alarm.  We don't actually want to go idle.
             if (mState != STATE_ACTIVE) {
-                becomeActiveLocked("alarm");
+                becomeActiveLocked("alarm", Process.myUid());
             }
             return;
         }
@@ -954,7 +968,7 @@
         // state to wait again for no motion.  Note that we only monitor for significant
         // motion after moving out of the inactive state, so no need to worry about that.
         if (mState != STATE_ACTIVE) {
-            scheduleReportActiveLocked(true);
+            scheduleReportActiveLocked("motion", Process.myUid());
             mState = STATE_ACTIVE;
             mInactiveTimeout = mConstants.MOTION_INACTIVE_TIMEOUT;
             EventLogTags.writeDeviceIdle(mState, "motion");
@@ -1240,7 +1254,7 @@
                     synchronized (this) {
                         if (!mIdleDisabled) {
                             mIdleDisabled = true;
-                            becomeActiveLocked("disabled");
+                            becomeActiveLocked("disabled", Process.myUid());
                             pw.println("Idle mode disabled");
                         }
                     }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 27983e2..1134556c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2488,10 +2488,7 @@
             synchronized(bstats) {
                 synchronized(mPidsSelfLocked) {
                     if (haveNewCpuStats) {
-                        final int perc = bstats.startAddingCpuLocked();
-                        if (perc >= 0) {
-                            int remainUTime = 0;
-                            int remainSTime = 0;
+                        if (bstats.startAddingCpuLocked()) {
                             int totalUTime = 0;
                             int totalSTime = 0;
                             final int N = mProcessCpuTracker.countStats();
@@ -2501,10 +2498,6 @@
                                     continue;
                                 }
                                 ProcessRecord pr = mPidsSelfLocked.get(st.pid);
-                                int otherUTime = (st.rel_utime*perc)/100;
-                                int otherSTime = (st.rel_stime*perc)/100;
-                                remainUTime += otherUTime;
-                                remainSTime += otherSTime;
                                 totalUTime += st.rel_utime;
                                 totalSTime += st.rel_stime;
                                 if (pr != null) {
@@ -2513,8 +2506,7 @@
                                         pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked(
                                                 pr.info.uid, pr.processName);
                                     }
-                                    ps.addCpuTimeLocked(st.rel_utime - otherUTime,
-                                            st.rel_stime - otherSTime);
+                                    ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
                                     pr.curCpuTime += st.rel_utime + st.rel_stime;
                                 } else {
                                     BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
@@ -2522,8 +2514,7 @@
                                         st.batteryStats = ps = bstats.getProcessStatsLocked(
                                                 bstats.mapUid(st.uid), st.name);
                                     }
-                                    ps.addCpuTimeLocked(st.rel_utime - otherUTime,
-                                            st.rel_stime - otherSTime);
+                                    ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
                                 }
                             }
                             final int userTime = mProcessCpuTracker.getLastUserTime();
@@ -2532,9 +2523,8 @@
                             final int irqTime = mProcessCpuTracker.getLastIrqTime();
                             final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime();
                             final int idleTime = mProcessCpuTracker.getLastIdleTime();
-                            bstats.finishAddingCpuLocked(perc, remainUTime,
-                                    remainSTime, totalUTime, totalSTime, userTime, systemTime,
-                                    iowaitTime, irqTime, softIrqTime, idleTime);
+                            bstats.finishAddingCpuLocked(totalUTime, totalSTime, userTime,
+                                    systemTime, iowaitTime, irqTime, softIrqTime, idleTime);
                         }
                     }
                 }
@@ -3274,9 +3264,9 @@
                     debugFlags |= Zygote.DEBUG_ENABLE_JIT;
                 }
             }
-            String genCFIDebugProperty = SystemProperties.get("debug.gencfi");
-            if ("true".equals(genCFIDebugProperty)) {
-                debugFlags |= Zygote.DEBUG_GENERATE_CFI;
+            String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");
+            if ("true".equals(genDebugInfoProperty)) {
+                debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;
             }
             if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
                 debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
@@ -8280,7 +8270,7 @@
                 try {
                     if (AppGlobals.getPackageManager().isUidPrivileged(callingUid)) {
                         allowed = true;
-                        Slog.w(TAG, caller + ": caller " + callingUid
+                        if (DEBUG_TASKS) Slog.w(TAG, caller + ": caller " + callingUid
                                 + " is using old GET_TASKS but privileged; allowing");
                     }
                 } catch (RemoteException e) {
@@ -8288,7 +8278,7 @@
             }
         }
         if (!allowed) {
-            Slog.w(TAG, caller + ": caller " + callingUid
+            if (DEBUG_TASKS) Slog.w(TAG, caller + ": caller " + callingUid
                     + " does not hold REAL_GET_TASKS; limiting output");
         }
         return allowed;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 9e33f2a..4e98576 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1915,7 +1915,12 @@
                 ActivityRecord intentActivity = !launchSingleInstance ?
                         findTaskLocked(r) : findActivityLocked(intent, r.info);
                 if (intentActivity != null) {
-                    if (isLockTaskModeViolation(intentActivity.task)) {
+                    // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused
+                    // but still needs to be a lock task mode violation since the task gets
+                    // cleared out and the device would otherwise leave the locked task.
+                    if (isLockTaskModeViolation(intentActivity.task,
+                            (launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
+                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
                         showLockTaskToast();
                         Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
                         return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
@@ -3780,7 +3785,11 @@
     }
 
     boolean isLockTaskModeViolation(TaskRecord task) {
-        if (getLockedTaskLocked() == task) {
+        return isLockTaskModeViolation(task, false);
+    }
+
+    boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) {
+        if (getLockedTaskLocked() == task && !isNewClearTask) {
             return false;
         }
         final int lockTaskAuth = task.mLockTaskAuth;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c973386..3854e51 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -42,6 +42,7 @@
 import android.telephony.TelephonyManager;
 import android.util.Slog;
 
+import android.util.TimeUtils;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.os.BatteryStatsHelper;
@@ -64,16 +65,22 @@
         implements PowerManagerInternal.LowPowerModeListener {
     static final String TAG = "BatteryStatsService";
 
-    private boolean mFirstExternalStatsUpdate = true;
     static IBatteryStats sService;
     final BatteryStatsImpl mStats;
     final BatteryStatsHandler mHandler;
     Context mContext;
     PowerManagerInternal mPowerManagerInternal;
 
+    final int UPDATE_CPU = 0x01;
+    final int UPDATE_WIFI = 0x02;
+    final int UPDATE_RADIO = 0x04;
+    final int UPDATE_BT = 0x08;
+    final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
+
     class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
         public static final int MSG_SYNC_EXTERNAL_STATS = 1;
         public static final int MSG_WRITE_TO_DISK = 2;
+        private int mUpdateFlags = 0;
 
         public BatteryStatsHandler(Looper looper) {
             super(looper);
@@ -83,11 +90,17 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_SYNC_EXTERNAL_STATS:
-                    updateExternalStats((String)msg.obj, false);
+                    final int updateFlags;
+                    synchronized (this) {
+                        removeMessages(MSG_SYNC_EXTERNAL_STATS);
+                        updateFlags = mUpdateFlags;
+                        mUpdateFlags = 0;
+                    }
+                    updateExternalStats((String)msg.obj, updateFlags);
                     break;
 
                 case MSG_WRITE_TO_DISK:
-                    updateExternalStats("write", true);
+                    updateExternalStats("write", UPDATE_ALL);
                     synchronized (mStats) {
                         mStats.writeAsyncLocked();
                     }
@@ -97,9 +110,20 @@
 
         @Override
         public void scheduleSync(String reason) {
-            if (!hasMessages(MSG_SYNC_EXTERNAL_STATS)) {
-                Message msg = Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason);
-                sendMessage(msg);
+            scheduleSyncImpl(reason, UPDATE_ALL);
+        }
+
+        @Override
+        public void scheduleWifiSync(String reason) {
+            scheduleSyncImpl(reason, UPDATE_WIFI);
+        }
+
+        private void scheduleSyncImpl(String reason, int updateFlags) {
+            synchronized (this) {
+                if (mUpdateFlags == 0) {
+                    sendMessage(Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason));
+                }
+                mUpdateFlags |= updateFlags;
             }
         }
     }
@@ -137,7 +161,7 @@
     public void shutdown() {
         Slog.w("BatteryStats", "Writing battery stats before shutdown...");
 
-        updateExternalStats("shutdown", true);
+        updateExternalStats("shutdown", UPDATE_ALL);
         synchronized (mStats) {
             mStats.shutdownLocked();
         }
@@ -237,7 +261,7 @@
         //Slog.i("foo", "SENDING BATTERY INFO:");
         //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
         Parcel out = Parcel.obtain();
-        updateExternalStats("get-stats", true);
+        updateExternalStats("get-stats", UPDATE_ALL);
         synchronized (mStats) {
             mStats.writeToParcel(out, 0);
         }
@@ -252,7 +276,7 @@
         //Slog.i("foo", "SENDING BATTERY INFO:");
         //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
         Parcel out = Parcel.obtain();
-        updateExternalStats("get-stats", true);
+        updateExternalStats("get-stats", UPDATE_ALL);
         synchronized (mStats) {
             mStats.writeToParcel(out, 0);
         }
@@ -603,8 +627,10 @@
 
         // There was a change in WiFi power state.
         // Collect data now for the past activity.
-        mHandler.scheduleSync("wifi-data");
         synchronized (mStats) {
+            if (mStats.isOnBattery()) {
+                mHandler.scheduleWifiSync("wifi-data");
+            }
             mStats.noteWifiRadioPowerState(powerState, tsNanos);
         }
     }
@@ -767,10 +793,10 @@
     }
 
     @Override
-    public void noteDeviceIdleMode(boolean enabled, boolean fromActive, boolean fromMotion) {
+    public void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteDeviceIdleModeLocked(enabled, fromActive, fromMotion);
+            mStats.noteDeviceIdleModeLocked(enabled, activeReason, activeUid);
         }
     }
 
@@ -807,7 +833,7 @@
 
         // Sync external stats first as the battery has changed states. If we don't sync
         // immediately here, we may not collect the relevant data later.
-        updateExternalStats("battery-state", false);
+        updateExternalStats("battery-state", UPDATE_ALL);
         synchronized (mStats) {
             mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
         }
@@ -961,9 +987,9 @@
                         pw.println("Battery stats reset.");
                         noOutput = true;
                     }
-                    updateExternalStats("dump", true);
+                    updateExternalStats("dump", UPDATE_ALL);
                 } else if ("--write".equals(arg)) {
-                    updateExternalStats("dump", true);
+                    updateExternalStats("dump", UPDATE_ALL);
                     synchronized (mStats) {
                         mStats.writeSyncLocked();
                         pw.println("Battery stats written.");
@@ -1027,7 +1053,7 @@
                 flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
             }
             // Fetch data from external sources and update the BatteryStatsImpl object with them.
-            updateExternalStats("dump", true);
+            updateExternalStats("dump", UPDATE_ALL);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -1119,6 +1145,12 @@
                     return null;
                 }
 
+                final long timePeriodMs = info.mTimestamp - mLastInfo.mTimestamp;
+                final long lastIdleMs = mLastInfo.mControllerIdleTimeMs;
+                final long lastTxMs = mLastInfo.mControllerTxTimeMs;
+                final long lastRxMs = mLastInfo.mControllerRxTimeMs;
+                final long lastEnergy = mLastInfo.mControllerEnergyUsed;
+
                 // We will modify the last info object to be the delta, and store the new
                 // WifiActivityEnergyInfo object as our last one.
                 final WifiActivityEnergyInfo result = mLastInfo;
@@ -1126,19 +1158,16 @@
                 result.mStackState = info.getStackState();
 
                 // These times seem to be the most reliable.
-                result.mControllerTxTimeMs =
-                        info.mControllerTxTimeMs - mLastInfo.mControllerTxTimeMs;
-                result.mControllerRxTimeMs =
-                        info.mControllerRxTimeMs - mLastInfo.mControllerRxTimeMs;
+                result.mControllerTxTimeMs = info.mControllerTxTimeMs - lastTxMs;
+                result.mControllerRxTimeMs = info.mControllerRxTimeMs - lastRxMs;
 
                 // WiFi calculates the idle time as a difference from the on time and the various
                 // Rx + Tx times. There seems to be some missing time there because this sometimes
                 // becomes negative. Just cap it at 0 and move on.
                 // b/21613534
-                result.mControllerIdleTimeMs =
-                        Math.max(0, info.mControllerIdleTimeMs - mLastInfo.mControllerIdleTimeMs);
+                result.mControllerIdleTimeMs = Math.max(0, info.mControllerIdleTimeMs - lastIdleMs);
                 result.mControllerEnergyUsed =
-                        Math.max(0, info.mControllerEnergyUsed - mLastInfo.mControllerEnergyUsed);
+                        Math.max(0, info.mControllerEnergyUsed - lastEnergy);
 
                 if (result.mControllerTxTimeMs < 0 ||
                         result.mControllerRxTimeMs < 0) {
@@ -1151,6 +1180,34 @@
 
                     Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + result);
                 }
+
+                final long totalTimeMs = result.mControllerIdleTimeMs + result.mControllerRxTimeMs +
+                        result.mControllerTxTimeMs;
+                if (totalTimeMs > timePeriodMs) {
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("Total time ");
+                    TimeUtils.formatDuration(totalTimeMs, sb);
+                    sb.append(" is longer than sample period ");
+                    TimeUtils.formatDuration(timePeriodMs, sb);
+                    sb.append(".\n");
+                    sb.append("Previous WiFi snapshot: ").append("idle=");
+                    TimeUtils.formatDuration(lastIdleMs, sb);
+                    sb.append(" rx=");
+                    TimeUtils.formatDuration(lastRxMs, sb);
+                    sb.append(" tx=");
+                    TimeUtils.formatDuration(lastTxMs, sb);
+                    sb.append(" e=").append(lastEnergy);
+                    sb.append("\n");
+                    sb.append("Current WiFi snapshot: ").append("idle=");
+                    TimeUtils.formatDuration(info.mControllerIdleTimeMs, sb);
+                    sb.append(" rx=");
+                    TimeUtils.formatDuration(info.mControllerRxTimeMs, sb);
+                    sb.append(" tx=");
+                    TimeUtils.formatDuration(info.mControllerTxTimeMs, sb);
+                    sb.append(" e=").append(info.mControllerEnergyUsed);
+                    Slog.wtf(TAG, sb.toString());
+                }
+
                 mLastInfo = info;
                 return result;
             }
@@ -1184,15 +1241,12 @@
      * We first grab a lock specific to this method, then once all the data has been collected,
      * we grab the mStats lock and update the data.
      *
-     * TODO(adamlesinski): When we start distributing bluetooth data to apps, we'll want to
-     * separate these external stats so that they can be collected individually and on different
-     * intervals.
-     *
      * @param reason The reason why this collection was requested. Useful for debugging.
-     * @param force If false, some stats may decide not to be collected for efficiency as their
-     *              results aren't needed immediately. When true, collect all stats unconditionally.
+     * @param updateFlags Which external stats to update. Can be a combination of
+     *                    {@link #UPDATE_CPU}, {@link #UPDATE_RADIO}, {@link #UPDATE_WIFI},
+     *                    and {@link #UPDATE_BT}.
      */
-    void updateExternalStats(String reason, boolean force) {
+    void updateExternalStats(final String reason, final int updateFlags) {
         synchronized (mExternalStatsLock) {
             if (mContext == null) {
                 // We haven't started yet (which means the BatteryStatsImpl object has
@@ -1200,34 +1254,46 @@
                 return;
             }
 
-            final WifiActivityEnergyInfo wifiEnergyInfo = pullWifiEnergyInfoLocked();
-            final BluetoothActivityEnergyInfo bluetoothEnergyInfo;
-            if (force) {
+            if (BatteryStatsImpl.DEBUG_ENERGY) {
+                Slog.d(TAG, "Updating external stats: reason=" + reason);
+            }
+
+            WifiActivityEnergyInfo wifiEnergyInfo = null;
+            if ((updateFlags & UPDATE_WIFI) != 0) {
+                wifiEnergyInfo = pullWifiEnergyInfoLocked();
+            }
+
+            BluetoothActivityEnergyInfo bluetoothEnergyInfo = null;
+            if ((updateFlags & UPDATE_BT) != 0) {
                 // We only pull bluetooth stats when we have to, as we are not distributing its
                 // use amongst apps and the sampling frequency does not matter.
                 bluetoothEnergyInfo = pullBluetoothEnergyInfoLocked();
-            } else {
-                bluetoothEnergyInfo = null;
             }
 
             synchronized (mStats) {
+                final long elapsedRealtime = SystemClock.elapsedRealtime();
+                final long uptime = SystemClock.uptimeMillis();
                 if (mStats.mRecordAllHistory) {
-                    final long elapsedRealtime = SystemClock.elapsedRealtime();
-                    final long uptime = SystemClock.uptimeMillis();
                     mStats.addHistoryEventLocked(elapsedRealtime, uptime,
                             BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS, reason, 0);
                 }
-                mStats.updateCpuTimeLocked(mFirstExternalStatsUpdate);
-                mStats.updateKernelWakelocksLocked();
-                mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime());
-                mStats.updateWifiStateLocked(wifiEnergyInfo);
-                mStats.updateBluetoothStateLocked(bluetoothEnergyInfo);
-            }
 
-            if (mFirstExternalStatsUpdate) {
-                // We have read the stats for the first time, which means we have a baseline
-                // from which to calculate delta.
-                mFirstExternalStatsUpdate = false;
+                if ((updateFlags & UPDATE_CPU) != 0) {
+                    mStats.updateCpuTimeLocked();
+                    mStats.updateKernelWakelocksLocked();
+                }
+
+                if ((updateFlags & UPDATE_RADIO) != 0) {
+                    mStats.updateMobileRadioStateLocked(elapsedRealtime);
+                }
+
+                if ((updateFlags & UPDATE_WIFI) != 0) {
+                    mStats.updateWifiStateLocked(wifiEnergyInfo);
+                }
+
+                if ((updateFlags & UPDATE_BT) != 0) {
+                    mStats.updateBluetoothStateLocked(bluetoothEnergyInfo);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 4ccb5ad..f72b598 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -46,10 +46,12 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.IDeviceIdleController;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.speech.RecognizerIntent;
@@ -1086,6 +1088,14 @@
             voiceIntent = new Intent(android.speech.RecognizerIntent.ACTION_WEB_SEARCH);
             Log.i(TAG, "voice-based interactions: about to use ACTION_WEB_SEARCH");
         } else {
+            IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+                    ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+            if (dic != null) {
+                try {
+                    dic.exitIdle("voice-search");
+                } catch (RemoteException e) {
+                }
+            }
             voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
             voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE,
                     isLocked && mKeyguardManager.isKeyguardSecure());
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6de81df..e7fddb9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8253,6 +8253,7 @@
             } else {
                 res.icon = info.icon;
             }
+            res.iconResourceId = info.icon;
             res.system = res.activityInfo.applicationInfo.isSystemApp();
             return res;
         }
@@ -12499,6 +12500,8 @@
                 if (clearPackagePreferredActivitiesLPw(packageName, removeUser)) {
                     scheduleWritePackageRestrictionsLocked(removeUser);
                 }
+                revokeRuntimePermissionsAndClearAllFlagsLocked(ps.getPermissionsState(),
+                        removeUser);
             }
             return true;
         }
@@ -12705,13 +12708,37 @@
                 | PackageManager.FLAG_PERMISSION_USER_FIXED
                 | PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
 
+        revokeRuntimePermissionsAndClearFlagsLocked(permissionsState, userId, userSetFlags);
+    }
+
+    /**
+     * Revokes granted runtime permissions and clears all flags.
+     *
+     * @param permissionsState The permission state to reset.
+     * @param userId The device user for which to do a reset.
+     */
+    private void revokeRuntimePermissionsAndClearAllFlagsLocked(
+            PermissionsState permissionsState, int userId) {
+        revokeRuntimePermissionsAndClearFlagsLocked(permissionsState, userId,
+                PackageManager.MASK_PERMISSION_FLAGS);
+    }
+
+    /**
+     * Revokes granted runtime permissions and clears certain flags.
+     *
+     * @param permissionsState The permission state to reset.
+     * @param userId The device user for which to do a reset.
+     * @param flags The flags that is going to be reset.
+     */
+    private void revokeRuntimePermissionsAndClearFlagsLocked(
+            PermissionsState permissionsState, int userId, int flags) {
         boolean needsWrite = false;
 
         for (PermissionState state : permissionsState.getRuntimePermissionStates(userId)) {
             BasePermission bp = mSettings.mPermissions.get(state.getName());
             if (bp != null) {
                 permissionsState.revokeRuntimePermission(bp, userId);
-                permissionsState.updatePermissionFlags(bp, userId, userSetFlags, 0);
+                permissionsState.updatePermissionFlags(bp, userId, flags, 0);
                 needsWrite = true;
             }
         }
@@ -14090,7 +14117,9 @@
                 }
             }
 
-            if (!checkin && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)) {
+            if (!checkin
+                    && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)
+                    && packageName == null) {
                 pw.println();
                 int count = mSettings.mPackages.size();
                 if (count == 0) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index cd50946..4b36581 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2098,7 +2098,7 @@
                 }
 
                 final ApplicationInfo ai = pkg.pkg.applicationInfo;
-                final String dataPath = ai.dataDir;
+                final String dataPath = new File(ai.dataDir).getCanonicalPath();
                 final boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
                 final int[] gids = pkg.getPermissionsState().computeGids(userIds);
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 6fb9a5c..bd545df 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -56,6 +56,7 @@
 import android.os.FactoryTest;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.IDeviceIdleController;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
@@ -2734,6 +2735,14 @@
                 if (!keyguardOn) {
                     voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
                 } else {
+                    IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+                            ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+                    if (dic != null) {
+                        try {
+                            dic.exitIdle("voice-search");
+                        } catch (RemoteException e) {
+                        }
+                    }
                     voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
                     voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true);
                 }
@@ -5192,6 +5201,14 @@
     }
 
     void launchVoiceAssistWithWakeLock(boolean keyguardActive) {
+        IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface(
+                ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+        if (dic != null) {
+            try {
+                dic.exitIdle("voice-search");
+            } catch (RemoteException e) {
+            }
+        }
         Intent voiceIntent =
             new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
         voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 58c3ea1..4692403 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -24,4 +24,5 @@
     void notificationLightPulse(int argb, int onMillis, int offMillis);
     void notificationLightOff();
     void showScreenPinningRequest();
+    void showAssistDisclosure();
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 5669f30..a754379 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -154,6 +154,16 @@
                 }
             }
         }
+
+        @Override
+        public void showAssistDisclosure() {
+            if (mBar != null) {
+                try {
+                    mBar.showAssistDisclosure();
+                } catch (RemoteException e) {
+                }
+            }
+        }
     };
 
     // ================================================================================
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index ac79b36..d4c5f87 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -40,8 +40,6 @@
     private boolean mRelroReady32Bit = false;
     private boolean mRelroReady64Bit = false;
 
-    private String oldWebViewPackageName = null;
-
     private BroadcastReceiver mWebViewUpdatedReceiver;
 
     public WebViewUpdateService(Context context) {
@@ -53,22 +51,9 @@
         mWebViewUpdatedReceiver = new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
-
-                    for (String packageName : WebViewFactory.getWebViewPackageNames()) {
-                        String webviewPackage = "package:" + packageName;
-
-                        if (webviewPackage.equals(intent.getDataString())) {
-                            String usedPackageName =
-                                WebViewFactory.findPreferredWebViewPackage().packageName;
-                            // Only trigger update actions if the updated package is the one that
-                            // will be used, or the one that was in use before the update.
-                            if (packageName.equals(usedPackageName) ||
-                                    packageName.equals(oldWebViewPackageName)) {
-                                onWebViewUpdateInstalled();
-                                oldWebViewPackageName = usedPackageName;
-                            }
-                            return;
-                        }
+                    String webviewPackage = "package:" + WebViewFactory.getWebViewPackageName();
+                    if (webviewPackage.equals(intent.getDataString())) {
+                        onWebViewUpdateInstalled();
                     }
                 }
         };
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index acd484d..af0ddbe 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -139,7 +139,7 @@
             IVoiceInteractionSessionShowCallback showCallback) {
         if (mActiveSession == null) {
             mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName,
-                    mUser, mContext, this, mInfo.getServiceInfo().applicationInfo.uid);
+                    mUser, mContext, this, mInfo.getServiceInfo().applicationInfo.uid, mHandler);
         }
         return mActiveSession.showLocked(args, flags, showCallback);
     }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 47a230a..cc6a9c5 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -32,6 +32,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -48,6 +49,8 @@
 import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.os.IResultReceiver;
+import com.android.server.LocalServices;
+import com.android.server.statusbar.StatusBarManagerInternal;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -63,6 +66,7 @@
     final Context mContext;
     final Callback mCallback;
     final int mCallingUid;
+    final Handler mHandler;
     final IActivityManager mAm;
     final IWindowManager mIWindowManager;
     final AppOpsManager mAppOps;
@@ -141,13 +145,14 @@
     };
 
     public VoiceInteractionSessionConnection(Object lock, ComponentName component, int user,
-            Context context, Callback callback, int callingUid) {
+            Context context, Callback callback, int callingUid, Handler handler) {
         mLock = lock;
         mSessionComponentName = component;
         mUser = user;
         mContext = context;
         mCallback = callback;
         mCallingUid = callingUid;
+        mHandler = handler;
         mAm = ActivityManagerNative.getDefault();
         mIWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -193,11 +198,13 @@
             mShowArgs = args;
             mShowFlags = flags;
             mHaveAssistData = false;
+            boolean needDisclosure = false;
             if ((flags& VoiceInteractionSession.SHOW_WITH_ASSIST) != 0) {
                 if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_STRUCTURE, mCallingUid,
                         mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
                         && allDataEnabled) {
                     try {
+                        needDisclosure = true;
                         mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
                                 mAssistReceiver);
                     } catch (RemoteException e) {
@@ -215,6 +222,7 @@
                         mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
                         && allDataEnabled) {
                     try {
+                        needDisclosure = true;
                         mIWindowManager.requestAssistScreenshot(mScreenshotReceiver);
                     } catch (RemoteException e) {
                     }
@@ -225,6 +233,9 @@
             } else {
                 mScreenshot = null;
             }
+            if (needDisclosure) {
+                mHandler.post(mShowAssistDisclosureRunnable);
+            }
             if (mSession != null) {
                 try {
                     mSession.show(mShowArgs, mShowFlags, showCallback);
@@ -483,4 +494,15 @@
             pw.print(prefix); pw.print("mAssistData="); pw.println(mAssistData);
         }
     }
+
+    private Runnable mShowAssistDisclosureRunnable = new Runnable() {
+        @Override
+        public void run() {
+            StatusBarManagerInternal statusBarInternal = LocalServices.getService(
+                    StatusBarManagerInternal.class);
+            if (statusBarInternal != null) {
+                statusBarInternal.showAssistDisclosure();
+            }
+        }
+    };
 };
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0eb94b8..01cab33 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -249,32 +249,24 @@
     /* The following 3 fields are related to carrier visual voicemail. */
 
     /**
-     * The carrier number MO sms messages are sent to.
-     *
-     * @hide
+     * The carrier number mobile outgoing (MO) sms messages are sent to.
      */
     public static final String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
 
     /**
-     * The port through which the MO sms messages are sent through.
-     *
-     * @hide
+     * The port through which the mobile outgoing (MO) sms messages are sent through.
      */
     public static final String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
 
     /**
      * The type of visual voicemail protocol the carrier adheres to. See {@link TelephonyManager}
      * for possible values. For example {@link TelephonyManager#VVM_TYPE_OMTP}.
-     *
-     * @hide
      */
     public static final String KEY_VVM_TYPE_STRING = "vvm_type_string";
 
     /**
      * The package name of the carrier's visual voicemail app to ensure that dialer visual voicemail
      * and carrier visual voicemail are not active at the same time.
-     *
-     * @hide
      */
     public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c6fadda..f77d268 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -616,15 +616,11 @@
 
     /**
      * The OMTP protocol.
-     *
-     * @hide
      */
     public static final String VVM_TYPE_OMTP = "vvm_type_omtp";
 
     /**
-     * A flavor of OMTP protocol for Comverse.
-     *
-     * @hide
+     * A flavor of OMTP protocol with a different mobile originated (MO) format
      */
     public static final String VVM_TYPE_CVVM = "vvm_type_cvvm";