Merge "Filter products during compile phase"
diff --git a/api/current.txt b/api/current.txt
index eb6ad09..4a1a458 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4760,6 +4760,7 @@
     method public android.graphics.drawable.Icon getLargeIcon();
     method public android.graphics.drawable.Icon getSmallIcon();
     method public java.lang.String getSortKey();
+    method public android.app.Notification.Topic[] getTopics();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
     field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -4924,6 +4925,7 @@
     method public android.app.Notification.Builder addAction(android.app.Notification.Action);
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification.Builder addPerson(java.lang.String);
+    method public android.app.Notification.Builder addTopic(android.app.Notification.Topic);
     method public android.app.Notification build();
     method public android.app.Notification.Builder extend(android.app.Notification.Extender);
     method public android.os.Bundle getExtras();
@@ -5031,6 +5033,16 @@
     field protected android.app.Notification.Builder mBuilder;
   }
 
+  public static class Notification.Topic implements android.os.Parcelable {
+    ctor public Notification.Topic(java.lang.String, java.lang.CharSequence);
+    method public android.app.Notification.Topic clone();
+    method public int describeContents();
+    method public java.lang.String getId();
+    method public java.lang.CharSequence getLabel();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.Notification.Topic> CREATOR;
+  }
+
   public static final class Notification.WearableExtender implements android.app.Notification.Extender {
     ctor public Notification.WearableExtender();
     ctor public Notification.WearableExtender(android.app.Notification);
diff --git a/api/system-current.txt b/api/system-current.txt
index 64ea3b8..ecea9b0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4877,6 +4877,7 @@
     method public android.graphics.drawable.Icon getLargeIcon();
     method public android.graphics.drawable.Icon getSmallIcon();
     method public java.lang.String getSortKey();
+    method public android.app.Notification.Topic[] getTopics();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
     field public static final java.lang.String CATEGORY_ALARM = "alarm";
@@ -5041,6 +5042,7 @@
     method public android.app.Notification.Builder addAction(android.app.Notification.Action);
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification.Builder addPerson(java.lang.String);
+    method public android.app.Notification.Builder addTopic(android.app.Notification.Topic);
     method public android.app.Notification build();
     method public android.app.Notification.Builder extend(android.app.Notification.Extender);
     method public android.os.Bundle getExtras();
@@ -5148,6 +5150,16 @@
     field protected android.app.Notification.Builder mBuilder;
   }
 
+  public static class Notification.Topic implements android.os.Parcelable {
+    ctor public Notification.Topic(java.lang.String, java.lang.CharSequence);
+    method public android.app.Notification.Topic clone();
+    method public int describeContents();
+    method public java.lang.String getId();
+    method public java.lang.CharSequence getLabel();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.Notification.Topic> CREATOR;
+  }
+
   public static final class Notification.WearableExtender implements android.app.Notification.Extender {
     ctor public Notification.WearableExtender();
     ctor public Notification.WearableExtender(android.app.Notification);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 81da6af..1e2e33d 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -120,7 +120,7 @@
         out.println(
                 "usage: am [subcommand] [options]\n" +
                 "usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" +
-                "               [--sampling INTERVAL] [-R COUNT] [-S] [--opengl-trace]\n" +
+                "               [--sampling INTERVAL] [-R COUNT] [-S]\n" +
                 "               [--track-allocation] [--user <USER_ID> | current] <INTENT>\n" +
                 "       am startservice [--user <USER_ID> | current] <INTENT>\n" +
                 "       am stopservice [--user <USER_ID> | current] <INTENT>\n" +
@@ -182,7 +182,6 @@
                 "    -R: repeat the activity launch <COUNT> times.  Prior to each repeat,\n" +
                 "        the top activity will be finished.\n" +
                 "    -S: force stop the target app before starting the activity\n" +
-                "    --opengl-trace: enable tracing of OpenGL functions\n" +
                 "    --track-allocation: enable tracking of object allocations\n" +
                 "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
                 "        specified then run as the current user.\n" +
@@ -739,8 +738,6 @@
                 mRepeat = Integer.parseInt(nextArgRequired());
             } else if (opt.equals("-S")) {
                 mStopOption = true;
-            } else if (opt.equals("--opengl-trace")) {
-                mStartFlags |= ActivityManager.START_FLAG_OPENGL_TRACES;
             } else if (opt.equals("--track-allocation")) {
                 mStartFlags |= ActivityManager.START_FLAG_TRACK_ALLOCATION;
             } else if (opt.equals("--user")) {
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 26c886e..0b751b2 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -23,9 +23,9 @@
 import android.graphics.PointF;
 import android.util.Log;
 import android.util.Property;
+import android.view.animation.AccelerateDecelerateInterpolator;
 
 import java.lang.ref.WeakReference;
-import java.util.ArrayList;
 
 /**
  * This subclass of {@link ValueAnimator} provides support for animating properties on target objects.
@@ -53,7 +53,8 @@
  * from the target object when the animator starts, just like animators with only one
  * value specified. In addition, an optional interpolator can be specified. The interpolator will
  * be applied on the interval between the keyframe that the interpolator is set on and the previous
- * keyframe. When no interpolator is supplied, the default linear interpolator will be used. </p>
+ * keyframe. When no interpolator is supplied, the default {@link AccelerateDecelerateInterpolator}
+ * will be used. </p>
  *
  * {@sample development/samples/ApiDemos/res/anim/object_animator_pvh_kf_interpolated.xml KeyframeResources}
  *
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d47c0aa..2f0849f 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -705,6 +705,8 @@
     private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";
     private static final String SAVED_DIALOG_KEY_PREFIX = "android:dialog_";
     private static final String SAVED_DIALOG_ARGS_KEY_PREFIX = "android:dialog_args_";
+    private static final String HAS_CURENT_PERMISSIONS_REQUEST_KEY =
+            "android:hasCurrentPermissionsRequest";
 
     private static final String REQUEST_PERMISSIONS_WHO_PREFIX = "@android:requestPermissions:";
 
@@ -813,6 +815,8 @@
     SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;
     SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK;
 
+    private boolean mHasCurrentPermissionsRequest;
+
     /** Return the intent that started this activity. */
     public Intent getIntent() {
         return mIntent;
@@ -1314,6 +1318,7 @@
         onSaveInstanceState(outState);
         saveManagedDialogs(outState);
         mActivityTransitionState.saveState(outState);
+        storeHasCurrentPermissionRequest(outState);
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState);
     }
 
@@ -1329,6 +1334,7 @@
     final void performSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
         onSaveInstanceState(outState, outPersistentState);
         saveManagedDialogs(outState);
+        storeHasCurrentPermissionRequest(outState);
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState +
                 ", " + outPersistentState);
     }
@@ -3862,8 +3868,15 @@
      * @see #shouldShowRequestPermissionRationale(String)
      */
     public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
+        if (mHasCurrentPermissionsRequest) {
+            Log.w(TAG, "Can reqeust only one set of permissions at a time");
+            // Dispatch the callback with empty arrays which means a cancellation.
+            onRequestPermissionsResult(requestCode, new String[0], new int[0]);
+            return;
+        }
         Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
         startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
+        mHasCurrentPermissionsRequest = true;
     }
 
     /**
@@ -6301,12 +6314,14 @@
     }
 
     final void performCreate(Bundle icicle) {
+        restoreHasCurrentPermissionRequest(icicle);
         onCreate(icicle);
         mActivityTransitionState.readState(icicle);
         performCreateCommon();
     }
 
     final void performCreate(Bundle icicle, PersistableBundle persistentState) {
+        restoreHasCurrentPermissionRequest(icicle);
         onCreate(icicle, persistentState);
         mActivityTransitionState.readState(icicle);
         performCreateCommon();
@@ -6489,6 +6504,19 @@
         return mResumed;
     }
 
+    private void storeHasCurrentPermissionRequest(Bundle bundle) {
+        if (bundle != null && mHasCurrentPermissionsRequest) {
+            bundle.putBoolean(HAS_CURENT_PERMISSIONS_REQUEST_KEY, true);
+        }
+    }
+
+    private void restoreHasCurrentPermissionRequest(Bundle bundle) {
+        if (bundle != null) {
+            mHasCurrentPermissionsRequest = bundle.getBoolean(
+                    HAS_CURENT_PERMISSIONS_REQUEST_KEY, false);
+        }
+    }
+
     void dispatchActivityResult(String who, int requestCode,
         int resultCode, Intent data) {
         if (false) Log.v(
@@ -6616,6 +6644,7 @@
     }
 
     private void dispatchRequestPermissionsResult(int requestCode, Intent data) {
+        mHasCurrentPermissionsRequest = false;
         // If the package installer crashed we may have not data - best effort.
         String[] permissions = (data != null) ? data.getStringArrayExtra(
                 PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES) : new String[0];
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 61a9a84..3bfeff0 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -204,17 +204,10 @@
 
     /**
      * Flag for IActivityManaqer.startActivity: launch the app for
-     * OpenGL tracing.
-     * @hide
-     */
-    public static final int START_FLAG_OPENGL_TRACES = 1<<2;
-
-    /**
-     * Flag for IActivityManaqer.startActivity: launch the app for
      * allocation tracking.
      * @hide
      */
-    public static final int START_FLAG_TRACK_ALLOCATION = 1<<3;
+    public static final int START_FLAG_TRACK_ALLOCATION = 1<<2;
 
     /**
      * Result for IActivityManaqer.broadcastIntent: success!
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index beaf3cf..b9292de 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -469,7 +469,6 @@
         IUiAutomationConnection instrumentationUiAutomationConnection;
         int debugMode;
         boolean enableBinderTracking;
-        boolean enableOpenGlTrace;
         boolean trackAllocation;
         boolean restrictedBackupMode;
         boolean persistent;
@@ -805,10 +804,9 @@
                 ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                 IInstrumentationWatcher instrumentationWatcher,
                 IUiAutomationConnection instrumentationUiConnection, int debugMode,
-                boolean enableBinderTracking, boolean enableOpenGlTrace,
-                boolean trackAllocation, boolean isRestrictedBackupMode,
-                boolean persistent, Configuration config, CompatibilityInfo compatInfo,
-                Map<String, IBinder> services, Bundle coreSettings) {
+                boolean enableBinderTracking, boolean trackAllocation,
+                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
+                CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {
 
             if (services != null) {
                 // Setup the service cache in the ServiceManager
@@ -864,7 +862,6 @@
             data.instrumentationUiAutomationConnection = instrumentationUiConnection;
             data.debugMode = debugMode;
             data.enableBinderTracking = enableBinderTracking;
-            data.enableOpenGlTrace = enableOpenGlTrace;
             data.trackAllocation = trackAllocation;
             data.restrictedBackupMode = isRestrictedBackupMode;
             data.persistent = persistent;
@@ -4776,11 +4773,6 @@
             }
         }
 
-        // Enable OpenGL tracing if required
-        if (data.enableOpenGlTrace) {
-            GLUtils.setTracingLevel(1);
-        }
-
         // Allow application-generated systrace messages if we're debuggable.
         boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
         Trace.setAppTracingAllowed(isAppDebuggable);
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index bead625..bfd9ca5 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -294,7 +294,6 @@
                     IUiAutomationConnection.Stub.asInterface(binder);
             int testMode = data.readInt();
             boolean enableBinderTracking = data.readInt() != 0;
-            boolean openGlTrace = data.readInt() != 0;
             boolean trackAllocation = data.readInt() != 0;
             boolean restrictedBackupMode = (data.readInt() != 0);
             boolean persistent = (data.readInt() != 0);
@@ -304,8 +303,8 @@
             Bundle coreSettings = data.readBundle();
             bindApplication(packageName, info, providers, testName, profilerInfo, testArgs,
                     testWatcher, uiAutomationConnection, testMode, enableBinderTracking,
-                    openGlTrace, trackAllocation, restrictedBackupMode, persistent, config,
-                    compatInfo, services, coreSettings);
+                    trackAllocation, restrictedBackupMode, persistent, config, compatInfo, services,
+                    coreSettings);
             return true;
         }
 
@@ -1020,10 +1019,9 @@
             List<ProviderInfo> providers, ComponentName testName, ProfilerInfo profilerInfo,
             Bundle testArgs, IInstrumentationWatcher testWatcher,
             IUiAutomationConnection uiAutomationConnection, int debugMode,
-            boolean enableBinderTracking, boolean openGlTrace, boolean trackAllocation,
-            boolean restrictedBackupMode, boolean persistent, Configuration config,
-            CompatibilityInfo compatInfo, Map<String, IBinder> services,
-            Bundle coreSettings) throws RemoteException {
+            boolean enableBinderTracking, boolean trackAllocation, boolean restrictedBackupMode,
+            boolean persistent, Configuration config, CompatibilityInfo compatInfo,
+            Map<String, IBinder> services, Bundle coreSettings) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeString(packageName);
@@ -1046,7 +1044,6 @@
         data.writeStrongInterface(uiAutomationConnection);
         data.writeInt(debugMode);
         data.writeInt(enableBinderTracking ? 1 : 0);
-        data.writeInt(openGlTrace ? 1 : 0);
         data.writeInt(trackAllocation ? 1 : 0);
         data.writeInt(restrictedBackupMode ? 1 : 0);
         data.writeInt(persistent ? 1 : 0);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 51d6132..046c87a 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2221,6 +2221,7 @@
             // This fragment was retained from a previous instance; get it
             // going now.
             fragment.mInLayout = true;
+            fragment.mHost = mHost;
             // If this fragment is newly instantiated (either right now, or
             // from last saved state), then give it the attributes to
             // initialize itself.
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 2d78e19..99e8853 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -96,10 +96,10 @@
     void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers,
             ComponentName testName, ProfilerInfo profilerInfo, Bundle testArguments,
             IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,
-            int debugMode, boolean enableBinderTracking, boolean openGlTrace,
-            boolean trackAllocation, boolean restrictedBackupMode, boolean persistent,
-            Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
-            Bundle coreSettings) throws RemoteException;
+            int debugMode, boolean enableBinderTracking, boolean trackAllocation,
+            boolean restrictedBackupMode, boolean persistent, Configuration config,
+            CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings)
+            throws RemoteException;
     void scheduleExit() throws RemoteException;
     void scheduleSuicide() throws RemoteException;
     void scheduleConfigurationChanged(Configuration config) throws RemoteException;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 55aec59..db18722 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -62,6 +62,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * A class that represents how a persistent notification is to be presented to
@@ -1362,6 +1363,95 @@
     public Notification publicVersion;
 
     /**
+     * Structure to encapsulate a topic that is shown in Notification settings.
+     * It must include an id and label.
+     */
+    public static class Topic implements Parcelable {
+        private final String id;
+        private final CharSequence label;
+
+        public Topic(String id, CharSequence label) {
+            this.id = id;
+            this.label = safeCharSequence(label);
+        }
+
+        private Topic(Parcel in) {
+            if (in.readInt() != 0) {
+                id = in.readString();
+            } else {
+                id = null;
+            }
+            label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+        }
+
+        public String getId() {
+            return id;
+        }
+
+        public CharSequence getLabel() {
+            return label;
+        }
+
+        @Override
+        public String toString() {
+            return new StringBuilder(Topic.class.getSimpleName()).append('[')
+                    .append("id=").append(id)
+                    .append(",label=").append(label)
+                    .append(']').toString();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof Topic)) return false;
+            if (o == this) return true;
+            final Topic other = (Topic) o;
+            return Objects.equals(other.id, id)
+                    && Objects.equals(other.label, label);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(id, label);
+        }
+
+        @Override
+        public Topic clone() {
+            return new Topic(id, label);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            if (id != null) {
+                out.writeInt(1);
+                out.writeString(id);
+            } else {
+                out.writeInt(0);
+            }
+            TextUtils.writeToParcel(label, out, flags);
+        }
+        public static final Parcelable.Creator<Topic> CREATOR =
+                new Parcelable.Creator<Topic>() {
+                    public Topic createFromParcel(Parcel in) {
+                        return new Topic(in);
+                    }
+                    public Topic[] newArray(int size) {
+                        return new Topic[size];
+                    }
+                };
+    }
+
+    private Topic[] topics;
+
+    public Topic[] getTopics() {
+        return topics;
+    }
+
+    /**
      * Constructs a Notification object with default values.
      * You might want to consider using {@link Builder} instead.
      */
@@ -1487,6 +1577,8 @@
         }
 
         color = parcel.readInt();
+
+        topics = parcel.createTypedArray(Topic.CREATOR); // may be null
     }
 
     @Override
@@ -1587,6 +1679,13 @@
 
         that.color = this.color;
 
+        if (this.topics != null) {
+            that.topics = new Topic[this.topics.length];
+            for(int i=0; i<this.topics.length; i++) {
+                that.topics[i] = this.topics[i].clone();
+            }
+        }
+
         if (!heavy) {
             that.lightenPayload(); // will clean out extras
         }
@@ -1759,6 +1858,8 @@
         }
 
         parcel.writeInt(color);
+
+        parcel.writeTypedArray(topics, 0); // null ok
     }
 
     /**
@@ -1895,6 +1996,18 @@
             sb.append(" publicVersion=");
             sb.append(publicVersion.toString());
         }
+        if (topics != null) {
+            sb.append("topics=[");
+            int N = topics.length;
+            if (N > 0) {
+                for (int i = 0; i < N-1; i++) {
+                    sb.append(topics[i]);
+                    sb.append(',');
+                }
+                sb.append(topics[N-1]);
+            }
+            sb.append("]");
+        }
         sb.append(")");
         return sb.toString();
     }
@@ -2105,6 +2218,7 @@
         private final NotificationColorUtil mColorUtil;
         private ArrayList<String> mPeople;
         private int mColor = COLOR_DEFAULT;
+        private List<Topic> mTopics = new ArrayList<>();
 
         /**
          * The user that built the notification originally.
@@ -2874,6 +2988,19 @@
             return this;
         }
 
+        /**
+         * Add a topic to this notification. Topics are typically displayed in Notification
+         * settings.
+         * <p>
+         * Every topic must have an id and a textual label.
+         *
+         * @param topic The topic to add.
+         */
+        public Builder addTopic(Topic topic) {
+            mTopics.add(topic);
+            return this;
+        }
+
         private Drawable getProfileBadgeDrawable() {
             // Note: This assumes that the current user can read the profile badge of the
             // originating user.
@@ -3364,6 +3491,10 @@
                 n.publicVersion = new Notification();
                 mPublicVersion.cloneInto(n.publicVersion, true);
             }
+            if (mTopics.size() > 0) {
+                n.topics = new Topic[mTopics.size()];
+                mTopics.toArray(n.topics);
+            }
             // Note: If you're adding new fields, also update restoreFromNotitification().
             return n;
         }
@@ -3605,6 +3736,10 @@
 
             mPublicVersion = n.publicVersion;
 
+            if (n.topics != null) {
+                Collections.addAll(mTopics, n.topics);
+            }
+
             // Extras.
             Bundle extras = n.extras;
             mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID);
diff --git a/core/java/android/content/PeriodicSync.java b/core/java/android/content/PeriodicSync.java
index 3efd89a..0441ccc 100644
--- a/core/java/android/content/PeriodicSync.java
+++ b/core/java/android/content/PeriodicSync.java
@@ -21,6 +21,8 @@
 import android.os.Parcel;
 import android.accounts.Account;
 
+import java.util.Objects;
+
 /**
  * Value type that contains information about a periodic sync.
  */
@@ -144,7 +146,9 @@
             if (!b2.containsKey(key)) {
                 return false;
             }
-            if (!b1.get(key).equals(b2.get(key))) {
+            // Null check. According to ContentResolver#validateSyncExtrasBundle null-valued keys
+            // are allowed in the bundle.
+            if (!Objects.equals(b1.get(key), b2.get(key))) {
                 return false;
             }
         }
diff --git a/core/java/android/ddm/DdmHandleViewDebug.java b/core/java/android/ddm/DdmHandleViewDebug.java
index be48633..5539dc9 100644
--- a/core/java/android/ddm/DdmHandleViewDebug.java
+++ b/core/java/android/ddm/DdmHandleViewDebug.java
@@ -16,7 +16,6 @@
 
 package android.ddm;
 
-import android.opengl.GLUtils;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewDebug;
@@ -41,9 +40,6 @@
  * Support for these features are advertised via {@link DdmHandleHello}.
  */
 public class DdmHandleViewDebug extends ChunkHandler {
-    /** Enable/Disable tracing of OpenGL calls. */
-    public static final int CHUNK_VUGL = type("VUGL");
-
     /** List {@link ViewRootImpl}'s of this process. */
     private static final int CHUNK_VULW = type("VULW");
 
@@ -97,7 +93,6 @@
     private DdmHandleViewDebug() {}
 
     public static void register() {
-        DdmServer.registerHandler(CHUNK_VUGL, sInstance);
         DdmServer.registerHandler(CHUNK_VULW, sInstance);
         DdmServer.registerHandler(CHUNK_VURT, sInstance);
         DdmServer.registerHandler(CHUNK_VUOP, sInstance);
@@ -115,9 +110,7 @@
     public Chunk handleChunk(Chunk request) {
         int type = request.type;
 
-        if (type == CHUNK_VUGL) {
-            return handleOpenGlTrace(request);
-        } else if (type == CHUNK_VULW) {
+        if (type == CHUNK_VULW) {
             return listWindows();
         }
 
@@ -165,12 +158,6 @@
         }
     }
 
-    private Chunk handleOpenGlTrace(Chunk request) {
-        ByteBuffer in = wrapChunk(request);
-        GLUtils.setTracingLevel(in.getInt());
-        return null;    // empty response
-    }
-
     /** Returns the list of windows owned by this client. */
     private Chunk listWindows() {
         String[] windowNames = WindowManagerGlobal.getInstance().getViewRootNames();
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 30cdfd3..2fe8fb6 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -78,14 +78,14 @@
                 sSensorModuleInitialized = true;
                 nativeClassInit();
             }
-        }
 
-        // initialize the sensor list
-        for (int index = 0;;++index) {
-            Sensor sensor = new Sensor();
-            if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
-            mFullSensorsList.add(sensor);
-            mHandleToSensor.append(sensor.getHandle(), sensor);
+            // initialize the sensor list
+            for (int index = 0;;++index) {
+                Sensor sensor = new Sensor();
+                if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
+                mFullSensorsList.add(sensor);
+                mHandleToSensor.append(sensor.getHandle(), sensor);
+            }
         }
     }
 
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8e86a53..1aa5c66 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -169,7 +169,7 @@
     /**
      * Current version of checkin data format.
      */
-    static final String CHECKIN_VERSION = "15";
+    static final String CHECKIN_VERSION = "16";
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
@@ -468,8 +468,8 @@
          * @param cluster the index of the CPU cluster.
          * @param step the index of the CPU speed. This is not the actual speed of the CPU.
          * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
-         * @see PowerProfile.getNumCpuClusters()
-         * @see PowerProfile.getNumSpeedStepsInCpuCluster(int)
+         * @see com.android.internal.os.PowerProfile#getNumCpuClusters()
+         * @see com.android.internal.os.PowerProfile#getNumSpeedStepsInCpuCluster(int)
          */
         public abstract long getTimeAtCpuSpeed(int cluster, int step, int which);
 
@@ -1135,14 +1135,15 @@
         public static final int STATE2_WIFI_RUNNING_FLAG = 1<<29;
         public static final int STATE2_WIFI_ON_FLAG = 1<<28;
         public static final int STATE2_FLASHLIGHT_FLAG = 1<<27;
-        public static final int STATE2_DEVICE_IDLE_FLAG = 1<<26;
-        public static final int STATE2_CHARGING_FLAG = 1<<25;
-        public static final int STATE2_PHONE_IN_CALL_FLAG = 1<<24;
-        public static final int STATE2_BLUETOOTH_ON_FLAG = 1<<23;
-        public static final int STATE2_CAMERA_FLAG = 1<<22;
+        public static final int STATE2_DEVICE_IDLE_SHIFT = 25;
+        public static final int STATE2_DEVICE_IDLE_MASK = 0x3 << STATE2_DEVICE_IDLE_SHIFT;
+        public static final int STATE2_CHARGING_FLAG = 1<<24;
+        public static final int STATE2_PHONE_IN_CALL_FLAG = 1<<23;
+        public static final int STATE2_BLUETOOTH_ON_FLAG = 1<<22;
+        public static final int STATE2_CAMERA_FLAG = 1<<21;
 
         public static final int MOST_INTERESTING_STATES2 =
-            STATE2_POWER_SAVE_FLAG | STATE2_WIFI_ON_FLAG | STATE2_DEVICE_IDLE_FLAG
+            STATE2_POWER_SAVE_FLAG | STATE2_WIFI_ON_FLAG | STATE2_DEVICE_IDLE_MASK
             | STATE2_CHARGING_FLAG | STATE2_PHONE_IN_CALL_FLAG | STATE2_BLUETOOTH_ON_FLAG;
 
         public static final int SETTLE_TO_ZERO_STATES2 = 0xffff0000 & ~MOST_INTERESTING_STATES2;
@@ -1620,36 +1621,57 @@
     public abstract int getPowerSaveModeEnabledCount(int which);
 
     /**
+     * Constant for device idle mode: not active.
+     */
+    public static final int DEVICE_IDLE_MODE_OFF = 0;
+
+    /**
+     * Constant for device idle mode: active in lightweight mode.
+     */
+    public static final int DEVICE_IDLE_MODE_LIGHT = 1;
+
+    /**
+     * Constant for device idle mode: active in full mode.
+     */
+    public static final int DEVICE_IDLE_MODE_FULL = 2;
+
+    /**
      * Returns the time in microseconds that device has been in idle mode while
      * running on battery.
      *
      * {@hide}
      */
-    public abstract long getDeviceIdleModeEnabledTime(long elapsedRealtimeUs, int which);
+    public abstract long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs, int which);
 
     /**
      * Returns the number of times that the devie has gone in to idle mode.
      *
      * {@hide}
      */
-    public abstract int getDeviceIdleModeEnabledCount(int which);
+    public abstract int getDeviceIdleModeCount(int mode, int which);
+
+    /**
+     * Return the longest duration we spent in a particular device idle mode (fully in the
+     * mode, not in idle maintenance etc).
+     */
+    public abstract long getLongestDeviceIdleModeTime(int mode);
 
     /**
      * Returns the time in microseconds that device has been in idling while on
-     * battery.  This is broader than {@link #getDeviceIdleModeEnabledTime} -- it
+     * battery.  This is broader than {@link #getDeviceIdleModeTime} -- it
      * counts all of the time that we consider the device to be idle, whether or not
      * it is currently in the actual device idle mode.
      *
      * {@hide}
      */
-    public abstract long getDeviceIdlingTime(long elapsedRealtimeUs, int which);
+    public abstract long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which);
 
     /**
      * Returns the number of times that the devie has started idling.
      *
      * {@hide}
      */
-    public abstract int getDeviceIdlingCount(int which);
+    public abstract int getDeviceIdlingCount(int mode, int which);
 
     /**
      * Returns the number of times that connectivity state changed.
@@ -1847,7 +1869,10 @@
         new BitDescription(HistoryItem.STATE2_WIFI_RUNNING_FLAG, "wifi_running", "Ww"),
         new BitDescription(HistoryItem.STATE2_WIFI_ON_FLAG, "wifi", "W"),
         new BitDescription(HistoryItem.STATE2_FLASHLIGHT_FLAG, "flashlight", "fl"),
-        new BitDescription(HistoryItem.STATE2_DEVICE_IDLE_FLAG, "device_idle", "di"),
+        new BitDescription(HistoryItem.STATE2_DEVICE_IDLE_MASK,
+                HistoryItem.STATE2_DEVICE_IDLE_SHIFT, "device_idle", "di",
+                new String[] { "off", "light", "full", "???" },
+                new String[] { "off", "light", "full", "???" }),
         new BitDescription(HistoryItem.STATE2_CHARGING_FLAG, "charging", "ch"),
         new BitDescription(HistoryItem.STATE2_PHONE_IN_CALL_FLAG, "phone_in_call", "Pcl"),
         new BitDescription(HistoryItem.STATE2_BLUETOOTH_ON_FLAG, "bluetooth", "b"),
@@ -2529,8 +2554,14 @@
         final long screenOnTime = getScreenOnTime(rawRealtime, which);
         final long interactiveTime = getInteractiveTime(rawRealtime, which);
         final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
-        final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which);
-        final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
+        final long deviceIdleModeLightTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT,
+                rawRealtime, which);
+        final long deviceIdleModeFullTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_FULL,
+                rawRealtime, which);
+        final long deviceLightIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_LIGHT,
+                rawRealtime, which);
+        final long deviceIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_FULL,
+                rawRealtime, which);
         final int connChanges = getNumConnectivityChange(which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
 
@@ -2613,11 +2644,15 @@
                 fullWakeLockTimeTotal / 1000, partialWakeLockTimeTotal / 1000,
                 getMobileRadioActiveTime(rawRealtime, which) / 1000,
                 getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000,
-                powerSaveModeEnabledTime / 1000, connChanges, deviceIdleModeEnabledTime / 1000,
-                getDeviceIdleModeEnabledCount(which), deviceIdlingTime / 1000,
-                getDeviceIdlingCount(which),
+                powerSaveModeEnabledTime / 1000, connChanges, deviceIdleModeFullTime / 1000,
+                getDeviceIdleModeCount(DEVICE_IDLE_MODE_FULL, which), deviceIdlingTime / 1000,
+                getDeviceIdlingCount(DEVICE_IDLE_MODE_FULL, which),
                 getMobileRadioActiveCount(which),
-                getMobileRadioActiveUnknownTime(which) / 1000);
+                getMobileRadioActiveUnknownTime(which) / 1000, deviceIdleModeLightTime / 1000,
+                getDeviceIdleModeCount(DEVICE_IDLE_MODE_LIGHT, which), deviceLightIdlingTime / 1000,
+                getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which),
+                getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT),
+                getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_FULL));
         
         // Dump screen brightness stats
         Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
@@ -3082,8 +3117,14 @@
         final long screenOnTime = getScreenOnTime(rawRealtime, which);
         final long interactiveTime = getInteractiveTime(rawRealtime, which);
         final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which);
-        final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which);
-        final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
+        final long deviceIdleModeLightTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT,
+                rawRealtime, which);
+        final long deviceIdleModeFullTime = getDeviceIdleModeTime(DEVICE_IDLE_MODE_FULL,
+                rawRealtime, which);
+        final long deviceLightIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_LIGHT,
+                rawRealtime, which);
+        final long deviceIdlingTime = getDeviceIdlingTime(DEVICE_IDLE_MODE_FULL,
+                rawRealtime, which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
         final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
         final long wifiOnTime = getWifiOnTime(rawRealtime, which);
@@ -3127,26 +3168,54 @@
                     sb.append(")");
             pw.println(sb.toString());
         }
-        if (deviceIdlingTime != 0) {
+        if (deviceLightIdlingTime != 0) {
             sb.setLength(0);
             sb.append(prefix);
-                    sb.append("  Device idling: ");
-                    formatTimeMs(sb, deviceIdlingTime / 1000);
+                    sb.append("  Device light idling: ");
+                    formatTimeMs(sb, deviceLightIdlingTime / 1000);
                     sb.append("(");
-                    sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime));
-                    sb.append(") "); sb.append(getDeviceIdlingCount(which));
+                    sb.append(formatRatioLocked(deviceLightIdlingTime, whichBatteryRealtime));
+                    sb.append(") "); sb.append(getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which));
                     sb.append("x");
             pw.println(sb.toString());
         }
-        if (deviceIdleModeEnabledTime != 0) {
+        if (deviceIdleModeLightTime != 0) {
             sb.setLength(0);
             sb.append(prefix);
-                    sb.append("  Idle mode time: ");
-                    formatTimeMs(sb, deviceIdleModeEnabledTime / 1000);
+                    sb.append("  Idle mode light time: ");
+                    formatTimeMs(sb, deviceIdleModeLightTime / 1000);
                     sb.append("(");
-                    sb.append(formatRatioLocked(deviceIdleModeEnabledTime, whichBatteryRealtime));
-                    sb.append(") "); sb.append(getDeviceIdleModeEnabledCount(which));
+                    sb.append(formatRatioLocked(deviceIdleModeLightTime, whichBatteryRealtime));
+                    sb.append(") ");
+                    sb.append(getDeviceIdleModeCount(DEVICE_IDLE_MODE_LIGHT, which));
                     sb.append("x");
+                    sb.append(" -- longest ");
+                    formatTimeMs(sb, getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT));
+            pw.println(sb.toString());
+        }
+        if (deviceIdlingTime != 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("  Device full idling: ");
+                    formatTimeMs(sb, deviceIdlingTime / 1000);
+                    sb.append("(");
+                    sb.append(formatRatioLocked(deviceIdlingTime, whichBatteryRealtime));
+                    sb.append(") "); sb.append(getDeviceIdlingCount(DEVICE_IDLE_MODE_FULL, which));
+                    sb.append("x");
+            pw.println(sb.toString());
+        }
+        if (deviceIdleModeFullTime != 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("  Idle mode full time: ");
+                    formatTimeMs(sb, deviceIdleModeFullTime / 1000);
+                    sb.append("(");
+                    sb.append(formatRatioLocked(deviceIdleModeFullTime, whichBatteryRealtime));
+                    sb.append(") ");
+                    sb.append(getDeviceIdleModeCount(DEVICE_IDLE_MODE_FULL, which));
+                    sb.append("x");
+                    sb.append(" -- longest ");
+                    formatTimeMs(sb, getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_FULL));
             pw.println(sb.toString());
         }
         if (phoneOnTime != 0) {
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 9fdbec3..dd10df3 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -47,6 +47,7 @@
     boolean isPowerSaveMode();
     boolean setPowerSaveMode(boolean mode);
     boolean isDeviceIdleMode();
+    boolean isLightDeviceIdleMode();
 
     void reboot(boolean confirm, String reason, boolean wait);
     void shutdown(boolean confirm, String reason, boolean wait);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 69974fa..1cffa83 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -910,6 +910,26 @@
     }
 
     /**
+     * Returns true if the device is currently in light idle mode.  This happens when a device
+     * has had its screen off for a short time, switching it into a batching mode where we
+     * execute jobs, syncs, networking on a batching schedule.  You can monitor for changes to
+     * this state with {@link #ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED}.
+     *
+     * @return Returns true if currently in active light device idle mode, else false.  This is
+     * when light idle mode restrictions are being actively applied; it will return false if the
+     * device is in a long-term idle mode but currently running a maintenance window where
+     * restrictions have been lifted.
+     * @hide
+     */
+    public boolean isLightDeviceIdleMode() {
+        try {
+            return mService.isLightDeviceIdleMode();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Return whether the given application package name is on the device's power whitelist.
      * Apps can be placed on the whitelist through the settings UI invoked by
      * {@link android.provider.Settings#ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS}.
@@ -961,6 +981,15 @@
             = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
 
     /**
+     * Intent that is broadcast when the state of {@link #isLightDeviceIdleMode()} changes.
+     * This broadcast is only sent to registered receivers.
+     * @hide
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED
+            = "android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED";
+
+    /**
      * @hide Intent that is broadcast when the set of power save whitelist apps has changed.
      * This broadcast is only sent to registered receivers.
      */
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index b6d0fcb..9801e1b 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -148,7 +148,9 @@
         public void onLowPowerModeChanged(boolean enabled);
     }
 
-    public abstract void setDeviceIdleMode(boolean enabled);
+    public abstract boolean setDeviceIdleMode(boolean enabled);
+
+    public abstract boolean setLightDeviceIdleMode(boolean enabled);
 
     public abstract void setDeviceIdleWhitelist(int[] appids);
 
diff --git a/core/java/android/test/AndroidTestCase.java b/core/java/android/test/AndroidTestCase.java
index 0635559..2ecbfae 100644
--- a/core/java/android/test/AndroidTestCase.java
+++ b/core/java/android/test/AndroidTestCase.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.test.suitebuilder.annotation.Suppress;
 
 import junit.framework.TestCase;
 
@@ -44,6 +45,7 @@
         super.tearDown();
     }
 
+    @Suppress
     public void testAndroidTestCaseSetupProperly() {
         assertNotNull("Context is null. setContext should be called before tests are run",
                 mContext);
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 6ece091..6a33579 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -627,7 +627,9 @@
 
                 chooseHt = getParagraphSpans(spanned, paraStart, paraEnd, LineHeightSpan.class);
 
-                if (chooseHt.length != 0) {
+                if (chooseHt.length == 0) {
+                    chooseHt = null; // So that out() would not assume it has any contents
+                } else {
                     if (chooseHtv == null ||
                         chooseHtv.length < chooseHt.length) {
                         chooseHtv = ArrayUtils.newUnpaddedIntArray(chooseHt.length);
@@ -810,7 +812,7 @@
 
                     v = out(source, here, endPos,
                             fmAscent, fmDescent, fmTop, fmBottom,
-                            v, spacingmult, spacingadd, chooseHt,chooseHtv, fm, flags[breakIndex],
+                            v, spacingmult, spacingadd, chooseHt, chooseHtv, fm, flags[breakIndex],
                             needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad,
                             chs, widths, paraStart, ellipsize, ellipsizedWidth,
                             lineWidths[breakIndex], paint, moreChars);
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index c82587b..6d1d893 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -432,23 +432,24 @@
                 return anim;
             }
         } else {
-            int startX = (Integer) startValues.values.get(PROPNAME_WINDOW_X);
-            int startY = (Integer) startValues.values.get(PROPNAME_WINDOW_Y);
-            int endX = (Integer) endValues.values.get(PROPNAME_WINDOW_X);
-            int endY = (Integer) endValues.values.get(PROPNAME_WINDOW_Y);
+            sceneRoot.getLocationInWindow(tempLocation);
+            int startX = (Integer) startValues.values.get(PROPNAME_WINDOW_X) - tempLocation[0];
+            int startY = (Integer) startValues.values.get(PROPNAME_WINDOW_Y) - tempLocation[1];
+            int endX = (Integer) endValues.values.get(PROPNAME_WINDOW_X) - tempLocation[0];
+            int endY = (Integer) endValues.values.get(PROPNAME_WINDOW_Y) - tempLocation[1];
             // TODO: also handle size changes: check bounds and animate size changes
             if (startX != endX || startY != endY) {
-                sceneRoot.getLocationInWindow(tempLocation);
-                Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
-                        Bitmap.Config.ARGB_8888);
+                final int width = view.getWidth();
+                final int height = view.getHeight();
+                Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
                 Canvas canvas = new Canvas(bitmap);
                 view.draw(canvas);
                 final BitmapDrawable drawable = new BitmapDrawable(bitmap);
+                drawable.setBounds(startX, startY, startX + width, startY + height);
                 final float transitionAlpha = view.getTransitionAlpha();
                 view.setTransitionAlpha(0);
                 sceneRoot.getOverlay().add(drawable);
-                Path topLeftPath = getPathMotion().getPath(startX - tempLocation[0],
-                        startY - tempLocation[1], endX - tempLocation[0], endY - tempLocation[1]);
+                Path topLeftPath = getPathMotion().getPath(startX, startY, endX, endY);
                 PropertyValuesHolder origin = PropertyValuesHolder.ofObject(
                         DRAWABLE_ORIGIN_PROPERTY, null, topLeftPath);
                 ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(drawable, origin);
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index e200bef..aa29636 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -547,9 +547,9 @@
                 // Don't retain static reference on context.
                 mConstructorArgs[0] = lastContext;
                 mConstructorArgs[1] = null;
-            }
 
-            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+            }
 
             return result;
         }
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 3cddbf6..3b9b8db 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -117,7 +117,7 @@
     void noteWifiRadioPowerState(int powerState, long timestampNs);
     void noteNetworkInterfaceType(String iface, int type);
     void noteNetworkStatsEnabled();
-    void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid);
+    void noteDeviceIdleMode(int mode, 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/logging/MetricsConstants.java b/core/java/com/android/internal/logging/MetricsConstants.java
index b90cb36..6cc8ba9 100644
--- a/core/java/com/android/internal/logging/MetricsConstants.java
+++ b/core/java/com/android/internal/logging/MetricsConstants.java
@@ -262,6 +262,24 @@
     public static final int TUNER_DEMO_MODE_ON = 236;
     public static final int TUNER_BATTERY_PERCENTAGE = 237;
     public static final int FUELGAUGE_INACTIVE_APPS = 238;
+    public static final int ACTION_ASSIST_LONG_PRESS = 239;
+    public static final int FINGERPRINT_ENROLLING = 240;
+    public static final int FINGERPRINT_FIND_SENSOR = 241;
+    public static final int FINGERPRINT_ENROLL_FINISH = 242;
+    public static final int FINGERPRINT_ENROLL_INTRO = 243;
+    public static final int FINGERPRINT_ENROLL_ONBOARD = 244;
+    public static final int FINGERPRINT_ENROLL_SIDECAR = 245;
+    public static final int FINGERPRINT_ENROLLING_SETUP = 246;
+    public static final int FINGERPRINT_FIND_SENSOR_SETUP = 247;
+    public static final int FINGERPRINT_ENROLL_FINISH_SETUP = 248;
+    public static final int FINGERPRINT_ENROLL_INTRO_SETUP = 249;
+    public static final int FINGERPRINT_ENROLL_ONBOARD_SETUP = 250;
+    public static final int ACTION_FINGERPRINT_ENROLL = 251;
+    public static final int ACTION_FINGERPRINT_AUTH = 252;
+    public static final int ACTION_FINGERPRINT_DELETE = 253;
+    public static final int ACTION_FINGERPRINT_RENAME = 254;
+    public static final int ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
+    public static final int ACTION_WIGGLE_CAMERA_GESTURE = 256;
 
     // These constants must match those in the analytic pipeline, do not edit.
     // Add temporary values to the top of MetricsLogger instead.
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index c25db65..2c5e50c 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -27,25 +27,6 @@
  */
 public class MetricsLogger implements MetricsConstants {
     // Temporary constants go here, to await migration to MetricsConstants.
-    // next value is 239;
-    public static final int ACTION_ASSIST_LONG_PRESS = 239;
-    public static final int FINGERPRINT_ENROLLING = 240;
-    public static final int FINGERPRINT_FIND_SENSOR = 241;
-    public static final int FINGERPRINT_ENROLL_FINISH = 242;
-    public static final int FINGERPRINT_ENROLL_INTRO = 243;
-    public static final int FINGERPRINT_ENROLL_ONBOARD = 244;
-    public static final int FINGERPRINT_ENROLL_SIDECAR = 245;
-    public static final int FINGERPRINT_ENROLLING_SETUP = 246;
-    public static final int FINGERPRINT_FIND_SENSOR_SETUP = 247;
-    public static final int FINGERPRINT_ENROLL_FINISH_SETUP = 248;
-    public static final int FINGERPRINT_ENROLL_INTRO_SETUP = 249;
-    public static final int FINGERPRINT_ENROLL_ONBOARD_SETUP = 250;
-    public static final int ACTION_FINGERPRINT_ENROLL = 251;
-    public static final int ACTION_FINGERPRINT_AUTH = 252;
-    public static final int ACTION_FINGERPRINT_DELETE = 253;
-    public static final int ACTION_FINGERPRINT_RENAME = 254;
-    public static final int ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
-    public static final int ACTION_WIGGLE_CAMERA_GESTURE = 256;
     public static final int QS_LOCK_TILE = 257;
     public static final int QS_USER_TILE = 258;
     public static final int QS_BATTERY_TILE = 259;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 64b7768..f73df00 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -105,7 +105,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 132 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 135 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -338,8 +338,15 @@
     boolean mDeviceIdling;
     StopwatchTimer mDeviceIdlingTimer;
 
-    boolean mDeviceIdleModeEnabled;
-    StopwatchTimer mDeviceIdleModeEnabledTimer;
+    boolean mDeviceLightIdling;
+    StopwatchTimer mDeviceLightIdlingTimer;
+
+    int mDeviceIdleMode;
+    long mLastIdleTimeStart;
+    long mLongestLightIdleTime;
+    long mLongestFullIdleTime;
+    StopwatchTimer mDeviceIdleModeLightTimer;
+    StopwatchTimer mDeviceIdleModeFullTimer;
 
     boolean mPhoneOn;
     StopwatchTimer mPhoneOnTimer;
@@ -3219,42 +3226,69 @@
         }
     }
 
-    public void noteDeviceIdleModeLocked(boolean enabled, String activeReason, int activeUid) {
+    public void noteDeviceIdleModeLocked(int mode, String activeReason, int activeUid) {
         final long elapsedRealtime = SystemClock.elapsedRealtime();
         final long uptime = SystemClock.uptimeMillis();
-        boolean nowIdling = enabled;
-        if (mDeviceIdling && !enabled && activeReason == null) {
+        boolean nowIdling = mode == DEVICE_IDLE_MODE_FULL;
+        if (mDeviceIdling && !nowIdling && 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;
         }
+        boolean nowLightIdling = mode == DEVICE_IDLE_MODE_LIGHT;
+        if (mDeviceLightIdling && !nowLightIdling && !nowIdling && activeReason == null) {
+            // We don't go out of general light idling mode until explicitly taken out of
+            // device idle through going active or significant motion.
+            nowLightIdling = true;
+        }
+        if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) {
+            addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE,
+                    activeReason, activeUid);
+        }
         if (mDeviceIdling != nowIdling) {
             mDeviceIdling = nowIdling;
             int stepState = nowIdling ? STEP_LEVEL_MODE_DEVICE_IDLE : 0;
             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState;
             mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState;
-            if (enabled) {
+            if (nowIdling) {
                 mDeviceIdlingTimer.startRunningLocked(elapsedRealtime);
             } else {
                 mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime);
             }
         }
-        if (mDeviceIdleModeEnabled != enabled) {
-            mDeviceIdleModeEnabled = enabled;
-            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: "
-                        + Integer.toHexString(mHistoryCur.states2));
-                mDeviceIdleModeEnabledTimer.startRunningLocked(elapsedRealtime);
+        if (mDeviceLightIdling != nowLightIdling) {
+            mDeviceLightIdling = nowLightIdling;
+            if (nowLightIdling) {
+                mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime);
             } else {
-                mHistoryCur.states2 &= ~HistoryItem.STATE2_DEVICE_IDLE_FLAG;
-                if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode disabled to: "
-                        + Integer.toHexString(mHistoryCur.states2));
-                mDeviceIdleModeEnabledTimer.stopRunningLocked(elapsedRealtime);
+                mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime);
             }
+        }
+        if (mDeviceIdleMode != mode) {
+            mHistoryCur.states2 = (mHistoryCur.states2 & ~HistoryItem.STATE2_DEVICE_IDLE_MASK)
+                    | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT);
+            if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: "
+                    + Integer.toHexString(mHistoryCur.states2));
             addHistoryRecordLocked(elapsedRealtime, uptime);
+            long lastDuration = elapsedRealtime - mLastIdleTimeStart;
+            mLastIdleTimeStart = elapsedRealtime;
+            if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) {
+                if (lastDuration > mLongestLightIdleTime) {
+                    mLongestLightIdleTime = lastDuration;
+                }
+                mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime);
+            } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_FULL) {
+                if (lastDuration > mLongestFullIdleTime) {
+                    mLongestFullIdleTime = lastDuration;
+                }
+                mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime);
+            }
+            if (mode == DEVICE_IDLE_MODE_LIGHT) {
+                mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime);
+            } else if (mode == DEVICE_IDLE_MODE_FULL) {
+                mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime);
+            }
+            mDeviceIdleMode = mode;
         }
     }
 
@@ -4140,20 +4174,55 @@
         return mPowerSaveModeEnabledTimer.getCountLocked(which);
     }
 
-    @Override public long getDeviceIdleModeEnabledTime(long elapsedRealtimeUs, int which) {
-        return mDeviceIdleModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+    @Override public long getDeviceIdleModeTime(int mode, long elapsedRealtimeUs,
+            int which) {
+        switch (mode) {
+            case DEVICE_IDLE_MODE_LIGHT:
+                return mDeviceIdleModeLightTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+            case DEVICE_IDLE_MODE_FULL:
+                return mDeviceIdleModeFullTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+        }
+        return 0;
     }
 
-    @Override public int getDeviceIdleModeEnabledCount(int which) {
-        return mDeviceIdleModeEnabledTimer.getCountLocked(which);
+    @Override public int getDeviceIdleModeCount(int mode, int which) {
+        switch (mode) {
+            case DEVICE_IDLE_MODE_LIGHT:
+                return mDeviceIdleModeLightTimer.getCountLocked(which);
+            case DEVICE_IDLE_MODE_FULL:
+                return mDeviceIdleModeFullTimer.getCountLocked(which);
+        }
+        return 0;
     }
 
-    @Override public long getDeviceIdlingTime(long elapsedRealtimeUs, int which) {
-        return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+    @Override public long getLongestDeviceIdleModeTime(int mode) {
+        switch (mode) {
+            case DEVICE_IDLE_MODE_LIGHT:
+                return mLongestLightIdleTime;
+            case DEVICE_IDLE_MODE_FULL:
+                return mLongestFullIdleTime;
+        }
+        return 0;
     }
 
-    @Override public int getDeviceIdlingCount(int which) {
-        return mDeviceIdlingTimer.getCountLocked(which);
+    @Override public long getDeviceIdlingTime(int mode, long elapsedRealtimeUs, int which) {
+        switch (mode) {
+            case DEVICE_IDLE_MODE_LIGHT:
+                return mDeviceLightIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+            case DEVICE_IDLE_MODE_FULL:
+                return mDeviceIdlingTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+        }
+        return 0;
+    }
+
+    @Override public int getDeviceIdlingCount(int mode, int which) {
+        switch (mode) {
+            case DEVICE_IDLE_MODE_LIGHT:
+                return mDeviceLightIdlingTimer.getCountLocked(which);
+            case DEVICE_IDLE_MODE_FULL:
+                return mDeviceIdlingTimer.getCountLocked(which);
+        }
+        return 0;
     }
 
     @Override public int getNumConnectivityChange(int which) {
@@ -6855,7 +6924,9 @@
         }
         mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase);
         mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase);
-        mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase);
+        mDeviceIdleModeLightTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase);
+        mDeviceIdleModeFullTimer = new StopwatchTimer(null, -14, null, mOnBatteryTimeBase);
+        mDeviceLightIdlingTimer = new StopwatchTimer(null, -15, null, mOnBatteryTimeBase);
         mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase);
         mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -7484,7 +7555,11 @@
         }
         mInteractiveTimer.reset(false);
         mPowerSaveModeEnabledTimer.reset(false);
-        mDeviceIdleModeEnabledTimer.reset(false);
+        mLongestLightIdleTime = 0;
+        mLongestFullIdleTime = 0;
+        mDeviceIdleModeLightTimer.reset(false);
+        mDeviceIdleModeFullTimer.reset(false);
+        mDeviceLightIdlingTimer.reset(false);
         mDeviceIdlingTimer.reset(false);
         mPhoneOnTimer.reset(false);
         mAudioOnTimer.reset(false);
@@ -9224,7 +9299,11 @@
         mInteractiveTimer.readSummaryFromParcelLocked(in);
         mPhoneOn = false;
         mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in);
-        mDeviceIdleModeEnabledTimer.readSummaryFromParcelLocked(in);
+        mLongestLightIdleTime = in.readLong();
+        mLongestFullIdleTime = in.readLong();
+        mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in);
+        mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in);
+        mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in);
         mDeviceIdlingTimer.readSummaryFromParcelLocked(in);
         mPhoneOnTimer.readSummaryFromParcelLocked(in);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -9558,7 +9637,11 @@
         }
         mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
-        mDeviceIdleModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+        out.writeLong(mLongestLightIdleTime);
+        out.writeLong(mLongestFullIdleTime);
+        mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+        mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+        mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mDeviceIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -9892,7 +9975,11 @@
         mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase, in);
         mPhoneOn = false;
         mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
-        mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase, in);
+        mLongestLightIdleTime = in.readLong();
+        mLongestFullIdleTime = in.readLong();
+        mDeviceIdleModeLightTimer = new StopwatchTimer(null, -14, null, mOnBatteryTimeBase, in);
+        mDeviceIdleModeFullTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase, in);
+        mDeviceLightIdlingTimer = new StopwatchTimer(null, -15, null, mOnBatteryTimeBase, in);
         mDeviceIdlingTimer = new StopwatchTimer(null, -12, null, mOnBatteryTimeBase, in);
         mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase, in);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -10053,7 +10140,11 @@
         }
         mInteractiveTimer.writeToParcel(out, uSecRealtime);
         mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime);
-        mDeviceIdleModeEnabledTimer.writeToParcel(out, uSecRealtime);
+        out.writeLong(mLongestLightIdleTime);
+        out.writeLong(mLongestFullIdleTime);
+        mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime);
+        mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime);
+        mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime);
         mDeviceIdlingTimer.writeToParcel(out, uSecRealtime);
         mPhoneOnTimer.writeToParcel(out, uSecRealtime);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -10188,8 +10279,12 @@
             mInteractiveTimer.logState(pr, "  ");
             pr.println("*** Power save mode timer:");
             mPowerSaveModeEnabledTimer.logState(pr, "  ");
-            pr.println("*** Device idle mode timer:");
-            mDeviceIdleModeEnabledTimer.logState(pr, "  ");
+            pr.println("*** Device idle mode light timer:");
+            mDeviceIdleModeLightTimer.logState(pr, "  ");
+            pr.println("*** Device idle mode full timer:");
+            mDeviceIdleModeFullTimer.logState(pr, "  ");
+            pr.println("*** Device light idling timer:");
+            mDeviceLightIdlingTimer.logState(pr, "  ");
             pr.println("*** Device idling timer:");
             mDeviceIdlingTimer.logState(pr, "  ");
             pr.println("*** Phone timer:");
diff --git a/core/jni/android/graphics/MinikinSkia.cpp b/core/jni/android/graphics/MinikinSkia.cpp
index 4649b07..8ac5d46 100644
--- a/core/jni/android/graphics/MinikinSkia.cpp
+++ b/core/jni/android/graphics/MinikinSkia.cpp
@@ -32,16 +32,6 @@
     SkSafeUnref(mTypeface);
 }
 
-bool MinikinFontSkia::GetGlyph(uint32_t codepoint, uint32_t *glyph) const {
-    SkPaint paint;
-    paint.setTypeface(mTypeface);
-    paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
-    uint16_t glyph16;
-    paint.textToGlyphs(&codepoint, sizeof(codepoint), &glyph16);
-    *glyph  = glyph16;
-    return !!glyph16;
-}
-
 static void MinikinFontSkia_SetSkiaPaint(const MinikinFont* font, SkPaint* skPaint, const MinikinPaint& paint) {
     skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
     skPaint->setTextSize(paint.size);
diff --git a/core/jni/android/graphics/MinikinSkia.h b/core/jni/android/graphics/MinikinSkia.h
index a06428d..8f469ba 100644
--- a/core/jni/android/graphics/MinikinSkia.h
+++ b/core/jni/android/graphics/MinikinSkia.h
@@ -28,8 +28,6 @@
 
     ~MinikinFontSkia();
 
-    bool GetGlyph(uint32_t codepoint, uint32_t *glyph) const;
-
     float GetHorizontalAdvance(uint32_t glyph_id,
         const MinikinPaint &paint) const;
 
@@ -54,4 +52,4 @@
 
 }  // namespace android
 
-#endif  // _ANDROID_GRAPHICS_MINIKIN_SKIA_H_
\ No newline at end of file
+#endif  // _ANDROID_GRAPHICS_MINIKIN_SKIA_H_
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index e045f5f..d4735ec 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -643,12 +643,6 @@
 
 // ---------------------------------------------------------------------------
 
-extern void setGLDebugLevel(int level);
-void setTracingLevel(JNIEnv *env, jclass clazz, jint level)
-{
-    setGLDebugLevel(level);
-}
-
 static int checkFormat(SkColorType colorType, int format, int type)
 {
     switch(colorType) {
@@ -1103,7 +1097,6 @@
     { "native_getType", "(Landroid/graphics/Bitmap;)I", (void*) util_getType },
     { "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D },
     { "native_texSubImage2D", "(IIIILandroid/graphics/Bitmap;II)I", (void*)util_texSubImage2D },
-    { "setTracingLevel", "(I)V",                        (void*)setTracingLevel },
 };
 
 static const JNINativeMethod gEtc1Methods[] = {
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 738a62a..cb0abb6 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -1660,10 +1660,11 @@
         uint32_t width = static_cast<uint32_t>(entry.data.i32[2]);
         uint32_t height = static_cast<uint32_t>(entry.data.i32[3]);
         if (entry2.count > 0 && entry2.count == lsmWidth * lsmHeight * 4) {
+            // GainMap rectangle is relative to the active area origin.
             err = builder.addGainMapsForMetadata(lsmWidth,
                                                  lsmHeight,
-                                                 ymin,
-                                                 xmin,
+                                                 0,
+                                                 0,
                                                  height,
                                                  width,
                                                  opcodeCfaLayout,
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 097bbac..1ee7ea8 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -294,7 +294,9 @@
                             // This is the regular Dalvik heap.
                             whichHeap = HEAP_DALVIK;
                             subHeap = HEAP_DALVIK_NORMAL;
-                        } else if (strstr(name, "/dev/ashmem/dalvik-large object space") == name) {
+                        } else if (strstr(name, "/dev/ashmem/dalvik-large object space") == name ||
+                                   strstr(name, "/dev/ashmem/dalvik-free list large object space")
+                                       == name) {
                             whichHeap = HEAP_DALVIK;
                             subHeap = HEAP_DALVIK_LARGE;
                         } else if (strstr(name, "/dev/ashmem/dalvik-non moving space") == name) {
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 2f1627b..a58ec89 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 uur lank</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (volgende wekker)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Totdat jy dit afskakel"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Totdat jy Moenie steur nie afskakel"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 5d94a69..80665a27 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">ለ%d ሰዓት</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"እስከ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ድረስ"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"እስከ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ቀጣይ ማንቂያ)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"ይህን እስኪያጠፉት ድረስ"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"አትረብሽን እስኪያጠፉ ድረስ"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 209e1dc..22eaabe 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1538,6 +1538,7 @@
       <item quantity="one">لمدة ساعة</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"حتى <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"حتى <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (التنبيه التالي)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"لحين تعطيل هذا الإعداد"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"حتى يتم تعطيل \"الرجاء عدم الإزعاج\""</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 16d123b..401e5b8 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 saat üçün</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Saat <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> qədər"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> radəsinə qədər (növbəti siqnal)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Bunu söndürənə kimi"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\"Narahat etməyin\" seçiminini deaktiv edənə kimi"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 5427659..6c3fa54 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">За 1 ч</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"До следващия будилник (<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Докато не изключите това"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Докато не изключите „Не безпокойте“"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 2d847ee..3f986a0 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">%d ঘন্টার জন্য</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> পর্যন্ত"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> পর্যন্ত (পরবর্তী অ্যালার্ম)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"আপনার দ্বারা এটি বন্ধ করা পর্যন্ত"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"যতক্ষণ না পর্যন্ত আপনি বিরক্ত করবেন না বন্ধ করছেন"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index e32c841..8d004df 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Durant 1 h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Fins a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Fins a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (propera alarma)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Fins que no ho desactivis"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Fins que desactivis el mode No molesteu"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 7b05612..6ead72f 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1504,6 +1504,7 @@
       <item quantity="one">1 h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (příští budík)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Dokud tuto funkci nevypnete"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokud nevypnete režim Nerušit"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 9c420c2..346cdb1 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">I %d t.</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Indtil <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Indtil <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (næste alarm)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Indtil du slår denne indstilling fra"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Indtil du slår \"Forstyr ikke\" fra"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index fcbd762..4e8b455 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Für 1 h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Bis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Bis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nächste Weckzeit)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Bis zur Deaktivierung"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Bis zur Deaktivierung von \"Nicht stören\""</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index f2bb1d5..3f5e1af 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Για 1 ώρα</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Έως τις <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Μέχρι τις <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (επόμενο ξυπνητήρι)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Μέχρι να το απενεργοποιήσετε"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Μέχρι να απενεργοποιήσετε τη ρύθμιση \"Μην ενοχλείτε\""</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index ea33448..22179ed 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">For 1 hr</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (next alarm)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Until you turn this off"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Until you turn off Do Not Disturb"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index ea33448..22179ed 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">For 1 hr</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (next alarm)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Until you turn this off"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Until you turn off Do Not Disturb"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index ea33448..22179ed 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">For 1 hr</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Until <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (next alarm)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Until you turn this off"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Until you turn off Do Not Disturb"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 5782eab..08f513b 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Durante 1 hora</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Hasta la(s) <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Hasta la hora <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próxima alarma)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Hasta que lo desactives"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hasta que desactives No molestar"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index bb44ed3..4d1500d 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Durante 1 hora</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Hasta las <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Hasta las <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próxima alarma)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Hasta apagar el dispositivo"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hasta que desactives la opción No molestar"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 98818ad..09454d6 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Kuni <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Kuni <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (järgmine äratus)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Kuni lülitate selle välja"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Kuni lülitate välja valiku Mitte segada"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 8e7193a..0815aeb 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Ordubetez</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> arte"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> arte (hurrengo alarma)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Zuk desaktibatu arte"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\"Ez molestatu\" desaktibatzen duzun arte"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 5032c25..683afb4 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -397,16 +397,16 @@
     <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"‏به برنامه اجازه می‌دهد تا بسته‌هایی را دریافت کند که در شبکه Wi-Fi با استفاده از آدرس‌های چندبخشی نه تنها به تلویزیون شما، بلکه به همه دستگاهها ارسال می‌شود. این حالت نسبت به حالت غیر چندبخشی از انرژی بیشتری استفاده می‌کند."</string>
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"‏به برنامه اجازه می‌دهد به دریافت بسته‌های ارسالی به همه دستگاه‌های موجود در شبکه Wi-Fi با استفاده از آدرس‌های پخش چندگانه و نه فقط به تلفن شما بپردازند. این از توان مصرف بیشتری نسبت به حالت پخش غیرچندگانه استفاده می‌کند."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"دسترسی به تنظیمات بلوتوث"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"‏به برنامه اجازه می‎دهد تا رایانهٔ لوحی بلوتوث محلی را پیکربندی کرده، دستگاه‌های راه دور را شناسایی کرده و با آن‌ها جفت شود."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"‏به برنامه اجازه می‎دهد تا رایانهٔ لوحی بلوتوث محلی را پیکربندی کرده، دستگاه‌های راه دور را شناسایی کرده و با آن‌ها مرتبط‌سازی شود."</string>
     <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"به برنامه اجازه می‌دهد تا تلویزیون بلوتوث محلی را پیکربندی کند و دستگاه‌های از راه دور را شناسایی کند و با آنها مرتبط شود."</string>
-    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"‏به برنامه اجازه می‎دهد تا تلفن بلوتوث محلی را پیکربندی کند و دستگاه‌های راه دور را پیدا کند و با آن‌ها جفت شود."</string>
+    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"‏به برنامه اجازه می‎دهد تا تلفن بلوتوث محلی را پیکربندی کند و دستگاه‌های راه دور را پیدا کند و با آن‌ها مرتبط‌سازی شود."</string>
     <string name="permlab_accessWimaxState" msgid="4195907010610205703">"‏اتصال و قطع اتصال از WiMAX"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"به برنامه امکان می‌دهد فعال بودن وایمکس و اطلاعات مربوط به هر یک از شبکه‌های وایمکس متصل را مشخص کند."</string>
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"‏تغییر وضعیت WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"به برنامه امکان می‌دهد رایانهٔ لوحی را به شبکه‌های وایمکس متصل کرده یا اتصال آن را از این شبکه‌ها قطع کند."</string>
     <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"‏به برنامه اجازه می‌دهد تا تلویزیون را به شبکه‌های WiMAX وصل یا ارتباط آن را با این شبکه‌ها قطع کند."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"‏به برنامه امکان می‎دهد تا تلفن را به شبکه‌های وایمکس متصل کرده یا اتصال آنرا از این شبکه‌ها قطع کند."</string>
-    <string name="permlab_bluetooth" msgid="6127769336339276828">"جفت کردن با دستگاه‌های بلوتوث"</string>
+    <string name="permlab_bluetooth" msgid="6127769336339276828">"مرتبط‌سازی با دستگاه‌های بلوتوث"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"‏به برنامه اجازه می‎دهد تا پیکربندی بلوتوث در رایانهٔ لوحی را مشاهده کند و اتصال با دستگاه‌های مرتبط را برقرار کرده و بپذیرد."</string>
     <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"به برنامه اجازه می‌دهد تا پیکربندی بلوتوث را در تلویزیون مشاهده کند و اتصالات را با دستگاه‌های مرتبط‌شده ایجاد کند و بپذیرد."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"‏به برنامه اجازه می‎دهد تا پیکربندی بلوتوث در تلفن را مشاهده کند، و اتصالات دستگاه‌های مرتبط را برقرار کرده و بپذیرد."</string>
@@ -1143,7 +1143,7 @@
     <string name="gpsNotifTitle" msgid="5446858717157416839">"درخواست موقعیت مکانی"</string>
     <string name="gpsNotifMessage" msgid="1374718023224000702">"درخواست شده توسط <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
     <string name="gpsVerifYes" msgid="2346566072867213563">"بله"</string>
-    <string name="gpsVerifNo" msgid="1146564937346454865">"خیر"</string>
+    <string name="gpsVerifNo" msgid="1146564937346454865">"نه"</string>
     <string name="sync_too_many_deletes" msgid="5296321850662746890">"از حد مجاز حذف فراتر رفت"</string>
     <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"‏<xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> مورد حذف شده برای <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>، حساب <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> وجود دارد. می‎خواهید چه کاری انجام دهید؟"</string>
     <string name="sync_really_delete" msgid="2572600103122596243">"حذف موارد"</string>
@@ -1470,6 +1470,7 @@
       <item quantity="other">‏برای %d ساعت</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"تا <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"تا <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (هشدار بعدی)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"تا وقتی آن را خاموش کنید"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"تا زمانی که «مزاحم نشوید» را خاموش کنید"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> /‏ <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 7298cba..f8fb76f7 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 tunnin ajan</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Kunnes kello on <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> asti (seuraava hälytys)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Kunnes poistat tämän käytöstä"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Kunnes poistat Varattu-tilan käytöstä."</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index ba17051..286459a 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">Pendant %d h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarme suivante)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Jusqu\'à ce que vous désactiviez le mode « Ne pas déranger »"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 15536cf..e4daeb1 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">Pendant %d h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarme suivante)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Jusqu\'à ce que vous désactiviez la fonctionnalité \"Ne pas déranger\""</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index c32add0..2abd2be 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Durante unha h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Ata as <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Ata as <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próxima alarma)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Ata que desactives isto"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Ata que desactives o modo Non molestar"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 6281abf..8f46194 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">%d કલાક માટે</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> સુધી"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (આગલા એલાર્મ) સુધી"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"તમે આ બંધ ન કરો ત્યાં સુધી"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"તમે ખલેલ પાડશો નહીં બંધ ન કરો ત્યાં સુધી"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 96eb95c..61b21bd 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">%d घंटे के लिए</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> तक"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (अगले अलार्म) तक"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"जब तक आप इसे बंद नहीं कर देते"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"जब तक कि आप परेशान ना करें को बंद नहीं कर देते"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 9b741bc..680dabd 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1487,6 +1487,7 @@
       <item quantity="other">%d h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (sljedeći alarm)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Dok ne isključite"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dok ne isključite \"Ne uznemiravaj\""</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b063f0c..faed9b9 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 órán keresztül</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Eddig: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Eddig: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ez a következő riasztás)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Amíg ki nem kapcsolja ezt"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Amíg ki nem kapcsolja a „Ne zavarjanak” lehetőséget"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index a295306..9a0e603 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">%d ժամով</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Մինչև <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Մինչև ժ. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-ը (հաջորդ զարթուցիչը)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Քանի դեռ չեք անջատել"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Մինչև չանջատեք «Չանհանգստացնել» գործառույթը"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 27f26a2..1bbd020 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Selama 1 jam</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Hingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Hingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarm berikutnya)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Hingga Anda menonaktifkan ini"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hingga Anda menonaktifkan status Jangan Ganggu"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index c09914b..2a97573 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">Í %d klst.</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Þangað til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (næsta viðvörun)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Þar til þú slekkur á þessu"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Þar til þú slekkur á „Ónáðið ekki“"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index a034a25..c56b41b 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Per 1 ora</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Fino alle ore <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Fino alle ore <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (prossima sveglia)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Fino alla disattivazione"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Fino alla disattivazione di Non disturbare"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a56332c..26fe698 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1504,6 +1504,7 @@
       <item quantity="one">למשך שעה אחת</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"עד <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"עד <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ההתראה הבאה)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"עד שתכבה"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"עד שתכבה את \'נא לא להפריע\'"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 135c7ea..6b1c833 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1時間</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>まで"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>(次のアラーム)まで"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"ユーザーがOFFにするまで"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"[通知を非表示]をOFFにするまで"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index df302f5..e1221c4 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 სთ.</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-მდე"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-მდე (შემდეგი მაღვიძარა)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"სანამ ამას გამორთავდეთ"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"სანამ გამორთავთ „არ შემაწუხოთ“ ფუნქციას"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 7af4df0..b3172ff 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 сағат</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> дейін"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> дейін (келесі дабыл)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Сіз осыны өшіргенше"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Өшірмейінше мазаламау"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 3a02e76..822a303 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1472,6 +1472,7 @@
       <item quantity="one">អស់រយៈពេល 1 ម៉ោង</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"រហូត​ដល់ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"រហូតដល់ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ម៉ោងរោទិ៍បន្ទាប់)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"រហូត​ដល់ពេល​​អ្នក​បិទ​វា"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"រហូតទាល់តែអ្នកបិទ កុំរំខាន"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 0e98430..73d7ffc 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">%d ಗಂಟೆಗೆ</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ವರೆಗೆ"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ವರೆಗೆ (ಮುಂದಿನ ಅಲಾರಮ್)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"ನೀವಿದನ್ನು ಆಫ್‌ ಮಾಡುವವರೆಗೆ"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"ನೀವು ಆಫ್ ಮಾಡುವವರೆಗೂ ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f5a6fa4..0d76af2 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1시간 동안</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>까지"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>(다음 알람)까지"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"이 기능을 사용 중지할 때까지"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"알림 일시중지 기능을 사용 중지할 때까지"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index f20551d..22399b0 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 саатка</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> чейин"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> чейин (кийинки ойготкуч)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Бул өчүрүлгөнгө чейин"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\"Тынчымды алба\" режими өчүрүлгөнгө чейин"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 2e58b116..1d39230 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">ເປັນ​ເວ​ລາ 1 ຊມ</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"ຈົນ​ຮອດ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"ຈົນ​ກ​່​ວາ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ສັນ​ຍານ​ເຕືອນ​ຕໍ່ໄປ​)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"ຈົນກວ່າ​ທ່ານ​ຈະ​ປິດ​"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"ຈົນ​ກ່​ວາ​ທ່ານ​ປິດ​ຫ້າມ​ລົບ​ກວນ"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index eb2903f..dbb8fbb 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1504,6 +1504,7 @@
       <item quantity="other">%d val.</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Iki <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Iki <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (kitas signalas)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Kol išjungsite"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Kol neišjungsite režimo „Netrukdyti“"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 7f10900..eaf7b46 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1487,6 +1487,7 @@
       <item quantity="other">%d h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Līdz <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Līdz plkst. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nākamais signāls)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Līdz brīdim, kad izslēgsiet"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Līdz izslēgsiet statusu “Netraucēt”"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index a41be56..17e0d49 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1472,6 +1472,7 @@
       <item quantity="other">За %d ч.</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (следниот аларм)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Додека не го исклучите"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Додека не го исклучите Не вознемирувај"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 2bdc9c8..3df3c86 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">ഒരു മണിക്കൂറത്തേക്ക്</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> വരെ"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> വരെ (അടുത്ത അലാറം)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"നിങ്ങൾ ഇത് ഓ‌ഫാക്കും വരെ"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\'ശല്ല്യപ്പെടുത്തരുത്\' ഓഫാക്കുന്നതുവരെ"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 3b5531d..ff8cc4d 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1468,6 +1468,7 @@
       <item quantity="one">1 цагийн турш:</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> хүртэл"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> хүртэл (дараагийн сэрүүлэг)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Таныг унтраах хүртэл"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"\"Бүү саад бол\"-ыг унтраах хүртэл"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 5956634..45bc3c5 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">%d तासासाठी</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> पर्यंत"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> पर्यंत (पुढील अलार्म)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"आपण हे बंद करेपर्यंत"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"आपण बंद करेपर्यंत व्यत्यय आणू नका"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index b69010e..1508d0e 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Selama 1 jam</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Sehingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Sehingga <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (penggera akan datang)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Sehingga anda matikan"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hingga anda mematikan Jangan Ganggu"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 41528d8..a09093f 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">၁ နာရီအတွက်</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>အထိ"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> အထိ (လာမည့် နှိုးစက်)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"သင်က ဒါကို ပိတ်မပစ်သည့် အထိ"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"မနှောင့်ယှက်ရန် ကိုသင်ပိတ်သည်အထိ"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b43314b..c2d2b80 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">I én time</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Til <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (neste alarm)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Inntil du slår av funksjonen"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Inntil du slår av Ikke forstyrr"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index ac52911..e4b6c22 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1476,6 +1476,7 @@
       <item quantity="one">१ घन्टाको लागि</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> सम्म"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (अर्को अलार्म) सम्म"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"तपाईँले यसलाई बन्द नगरेसम्म"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"तपाईँले बन्द नगरे सम्म बाधा नपुर्याउँनुहोस्"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index a850943..b208f48 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Gedurende 1 u</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Tot <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (volgend alarm)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Totdat u dit uitschakelt"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Totdat u \'Niet storen\' uitschakelt"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index e1276f1..8272d71 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">%d ਘੰਟਿਆਂ ਲਈ</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ਤੱਕ"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ਤੱਕ (ਅਗਲਾ ਅਲਾਰਮ)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸਨੂੰ ਬੰਦ ਨਹੀਂ ਕਰਦੇ ਹੋ"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਨੂੰ ਬੰਦ ਨਹੀਂ ਕਰਦੇ ਹੋ"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 0ef89a6..34d26dc 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1504,6 +1504,7 @@
       <item quantity="one">1 godz.</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (następny alarm)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Dopóki nie wyłączysz"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Do wyłączenia Nie przeszkadzać"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 2f6c8bf..bd1b2f0 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">Por %d horas</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Até você desativar"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Até que você desative \"Não perturbe\""</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index e14303d..897dcd6 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Durante 1 h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Até que o utilizador desative"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Até desativar Não incomodar"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 2f6c8bf..bd1b2f0 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">Por %d horas</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Até você desativar"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Até que você desative \"Não perturbe\""</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 1faa14f..428e139 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1487,6 +1487,7 @@
       <item quantity="one">Pentru 1 h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Până la <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Până la <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (următoarea alarmă)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Până la dezactivare"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Până când dezactivați „Nu deranja”"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 0621bbe..525e088 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1504,6 +1504,7 @@
       <item quantity="other">На %d часа</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Следующий сигнал в <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Пока я не отключу"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Пока вы не отключите режим \"Не беспокоить\""</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 582f912..0135884 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1472,6 +1472,7 @@
       <item quantity="other">පැය %d ක් සඳහා</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> තෙක්"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> තෙක් (ඊළඟ එලාමය)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"ඔබ මෙය අක්‍රිය කරන තුරු"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"බාධා නොකරන්න ඔබ අක්‍රිය කරන තුරු"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 8432348..5bd6867 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1504,6 +1504,7 @@
       <item quantity="one">Na 1 h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ďalší budík)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Dokým túto funkciu nevypnete"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokým nevypnete stav Nerušiť"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index c5ca3c2..02a748b3 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1504,6 +1504,7 @@
       <item quantity="other">%d h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (naslednji alarm)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Dokler tega ne izklopite"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokler ne izklopite načina »ne moti«"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index 7df0f86..128dc23 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Për 1 orë</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Deri në <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Deri në <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarmi tjetër)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Deri sa ta çaktivizosh këtë"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Deri sa të çaktivizosh gjendjen \"Mos shqetëso\""</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 5bb2d78..aec317e 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1487,6 +1487,7 @@
       <item quantity="other">За %d с</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (следећи аларм)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Док не искључите"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Док не искључите режим Не узнемиравај"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index e803cbb..1032768 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1182,7 +1182,7 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Dela med"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Dela med <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Skärmlåsfunktion. Tryck och dra."</string>
-    <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Lås upp genom att dra."</string>
+    <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Lås upp genom att svepa."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Anslut mikrofonlurar om du vill att lösenordet ska läsas upp."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkt."</string>
     <string name="action_bar_home_description" msgid="5293600496601490216">"Visa startsidan"</string>
@@ -1470,6 +1470,7 @@
       <item quantity="one">I en 1 tim</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Till kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Till <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nästa alarm)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Tills du inaktiverar detta"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Tills du inaktiverar Stör ej"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index af04a46..6cc7b13 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1472,6 +1472,7 @@
       <item quantity="one">Kwa saa 1 </item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Hadi <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Mpaka <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (kengele inayofuata)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Hadi utakapozima hili"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hadi utakapozima Usinisumbue"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 569fe82..1cdd590 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 மணிநேரத்திற்கு</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> வரை"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> மணி (அடுத்த அலாரம்) வரை"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"இதை முடக்கும்வரை"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"தொந்தரவு செய்ய வேண்டாம் என்பதை முடக்கும் வரை"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 77588b3..11c382e 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 గం పాటు</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> వరకు"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (తదుపరి అలారం) వరకు"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"మీరు దీన్ని ఆఫ్ చేసే వరకు"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"మీరు అంతరాయం కలిగించవద్దు ఎంపిక ఆఫ్ చేసే వరకు"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b2df636..d061873 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">เป็นเวลา 1 ชม.</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"จนถึงเวลา <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"จนถึงเวลา <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (การปลุกครั้งถัดไป)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"จนกว่าคุณจะปิดฟังก์ชันนี้"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"จนกว่าคุณจะปิดห้ามรบกวน"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 78c9358c..d87d7a9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">Sa loob ng %d na oras</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Hanggang <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Hanggang <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (susunod na alarm)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Hanggang sa i-off mo ito"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Hanggang sa i-off mo ang Huwag Istorbohin"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index bf046e3..a5917e5 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 saat için</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Şu saate kadar: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (sonraki alarma) saatine kadar"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Siz bunu kapatana kadar"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Rahatsız Etmeyin ayarını kapatana kadar"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 1aa1a51..6f77952 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1504,6 +1504,7 @@
       <item quantity="other">Протягом %d год</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"До <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (наступний будильник)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Доки ви не вимкнете"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Доки ввімкнено режим \"Не турбувати\""</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index e6e20f1..55e6efd 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 گھنٹہ کیلئے</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> تک"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> تک (اگلا الارم)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"جب تک آپ اسے آف نہ کر دیں"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"جب تک آپ ڈسڑب نہ کریں کو آف نہیں کر دیتے"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index b7ae992..c76df70 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 soat</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Ushbu vaqtgacha: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> gacha (keyingi signal)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Men o‘chirmaguncha"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"“Bezovta qilinmasin” rejimi o‘chirilmaguncha"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 83b0d18..a74e10e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">Trong 1 giờ</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Cho đến <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Cho tới <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (cảnh báo tiếp theo)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Cho đến khi bạn tắt tính năng này"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Cho đến khi bạn tắt Đừng làm phiền"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 54100d5..57c91a8 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 小时</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"到<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"直到<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>(闹钟下次响铃时)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"直到您将其关闭"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"直到您关闭“勿扰”模式"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 4c713c9..5b6b456 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">需時 1 小時</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"完成時間:<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"直至<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (下一次響鬧)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"直至您關閉這項設定"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"直至您關閉「請勿騷擾」功能"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 46f0d2c..387f8bb 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="one">1 小時</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"結束時間:<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"到<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> 為止 (下一個鬧鐘)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"手動關閉這項設定前一律啟用"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"直到您關閉「零打擾」模式"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 0ecd571..a9b6d14 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1470,6 +1470,7 @@
       <item quantity="other">Ngamahora angu-%d</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Kuze kube ngu-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+    <string name="zen_mode_alarm" msgid="9128205721301330797">"Kuze kube ngu-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (i-alamu elandelayo)"</string>
     <string name="zen_mode_forever" msgid="7420011936770086993">"Uze uvale lokhu"</string>
     <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Uze uvale ungaphazamisi"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 40cd097..c8d53d7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1697,7 +1697,7 @@
                                           --> <skip />
 
     <!-- On the keyguard screen, it shows the carrier the phone is connected to.  This is displayed if the phone is not connected to a carrier.-->
-    <string name="lockscreen_carrier_default">No service.</string>
+    <string name="lockscreen_carrier_default">No service</string>
 
     <!-- Shown in the lock screen to tell the user that the screen is locked. -->
     <string name="lockscreen_screen_locked">Screen locked.</string>
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 1105ca4..5988781 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -1569,16 +1569,16 @@
         public boolean onStateChange(int[] stateSet) {
             boolean changed = false;
 
-            if (mStrokeColors != null && mStrokeColors.isStateful()) {
-                final int strokeColor = mStrokeColor;
-                mStrokeColor = mStrokeColors.getColorForState(stateSet, strokeColor);
-                changed |= strokeColor != mStrokeColor;
+            if (mStrokeColors != null) {
+                final int oldStrokeColor = mStrokeColor;
+                mStrokeColor = mStrokeColors.getColorForState(stateSet, oldStrokeColor);
+                changed |= oldStrokeColor != mStrokeColor;
             }
 
-            if (mFillColors != null && mFillColors.isStateful()) {
-                final int fillColor = mFillColor;
-                mFillColor = mFillColors.getColorForState(stateSet, fillColor);
-                changed |= fillColor != mFillColor;
+            if (mFillColors != null) {
+                final int oldFillColor = mFillColor;
+                mFillColor = mFillColors.getColorForState(stateSet, oldFillColor);
+                changed |= oldFillColor != mFillColor;
             }
 
             return changed;
@@ -1586,8 +1586,7 @@
 
         @Override
         public boolean isStateful() {
-            return mStrokeColors != null && mStrokeColors.isStateful()
-                    || mFillColors != null && mFillColors.isStateful();
+            return mStrokeColors != null || mFillColors != null;
         }
 
         @Override
@@ -1716,31 +1715,31 @@
             final ColorStateList fillColors = a.getColorStateList(
                     R.styleable.VectorDrawablePath_fillColor);
             if (fillColors != null) {
-                mFillColors = fillColors;
+                // If the color state list isn't stateful, discard the state
+                // list and keep the default (e.g. the only) color.
+                mFillColors = fillColors.isStateful() ? fillColors : null;
                 mFillColor = fillColors.getDefaultColor();
             }
 
             final ColorStateList strokeColors = a.getColorStateList(
                     R.styleable.VectorDrawablePath_strokeColor);
             if (strokeColors != null) {
-                mStrokeColors = strokeColors;
+                // If the color state list isn't stateful, discard the state
+                // list and keep the default (e.g. the only) color.
+                mStrokeColors = strokeColors.isStateful() ? strokeColors : null;
                 mStrokeColor = strokeColors.getDefaultColor();
             }
 
-            mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha,
-                    mFillAlpha);
+            mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha, mFillAlpha);
             mStrokeLineCap = getStrokeLineCap(a.getInt(
                     R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
             mStrokeLineJoin = getStrokeLineJoin(a.getInt(
                     R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
             mStrokeMiterlimit = a.getFloat(
                     R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
-            mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha,
-                    mStrokeAlpha);
-            mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth,
-                    mStrokeWidth);
-            mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd,
-                    mTrimPathEnd);
+            mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha, mStrokeAlpha);
+            mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, mStrokeWidth);
+            mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, mTrimPathEnd);
             mTrimPathOffset = a.getFloat(
                     R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
             mTrimPathStart = a.getFloat(
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 9fc3924..1a43658 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -87,7 +87,6 @@
     -Wall -Wno-unused-parameter -Wunreachable-code \
     -ffast-math -O3 -Werror
 
-
 ifeq (true, $(HWUI_NEW_OPS))
     hwui_src_files += \
         BakedOpRenderer.cpp \
@@ -154,6 +153,27 @@
 include $(BUILD_STATIC_LIBRARY)
 
 # ------------------------
+# static library null gpu
+# ------------------------
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := libhwui_static_null_gpu
+LOCAL_SHARED_LIBRARIES := $(hwui_shared_libraries)
+LOCAL_CFLAGS := \
+        $(hwui_cflags) \
+        -DHWUI_NULL_GPU
+LOCAL_SRC_FILES := \
+        $(hwui_src_files) \
+        tests/nullegl.cpp \
+        tests/nullgles.cpp
+LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(hwui_c_includes) $(call hwui_proto_include)
+
+include $(BUILD_STATIC_LIBRARY)
+
+# ------------------------
 # shared library
 # ------------------------
 
@@ -175,7 +195,7 @@
 LOCAL_MODULE := hwui_unit_tests
 LOCAL_MODULE_TAGS := tests
 LOCAL_SHARED_LIBRARIES := $(hwui_shared_libraries)
-LOCAL_STATIC_LIBRARIES := libhwui_static
+LOCAL_STATIC_LIBRARIES := libhwui_static_null_gpu
 LOCAL_CFLAGS := $(hwui_cflags)
 
 LOCAL_SRC_FILES += \
@@ -210,22 +230,8 @@
 LOCAL_SHARED_LIBRARIES := $(hwui_shared_libraries)
 LOCAL_CFLAGS := $(hwui_cflags)
 
-HWUI_NULL_GPU := false
-
-ifeq (true, $(HWUI_NULL_GPU))
-    # Only need to specify the includes if we are not linking against
-    # libhwui_static as libhwui_static exports the appropriate includes
-    LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
-
-    LOCAL_SRC_FILES := \
-        $(hwui_src_files) \
-        tests/nullegl.cpp \
-        tests/nullgles.cpp
-
-    LOCAL_CFLAGS += -DHWUI_NULL_GPU
-else
-    LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static
-endif
+# set to libhwui_static_null_gpu to skip actual GL commands
+LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static
 
 LOCAL_SRC_FILES += \
     tests/TestContext.cpp \
@@ -250,7 +256,7 @@
 LOCAL_CFLAGS := $(hwui_cflags)
 LOCAL_C_INCLUDES += bionic/benchmarks/
 
-LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static
+LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static_null_gpu
 LOCAL_STATIC_LIBRARIES := libbenchmark libbase
 
 LOCAL_SRC_FILES += \
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 4eb7066..59f0d7c 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -34,6 +34,17 @@
 
 DisplayList::DisplayList()
         : projectionReceiveIndex(-1)
+        , stdAllocator(allocator)
+        , chunks(stdAllocator)
+        , ops(stdAllocator)
+        , children(stdAllocator)
+        , bitmapResources(stdAllocator)
+        , pathResources(stdAllocator)
+        , patchResources(stdAllocator)
+        , paints(stdAllocator)
+        , regions(stdAllocator)
+        , referenceHolders(stdAllocator)
+        , functors(stdAllocator)
         , hasDrawOps(false) {
 }
 
@@ -68,9 +79,9 @@
 }
 
 size_t DisplayList::addChild(NodeOpType* op) {
-    mReferenceHolders.push_back(op->renderNode);
-    size_t index = mChildren.size();
-    mChildren.push_back(op);
+    referenceHolders.push_back(op->renderNode);
+    size_t index = children.size();
+    children.push_back(op);
     return index;
 }
 
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index d32406f..86796c5 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -132,32 +132,22 @@
     DisplayList();
     ~DisplayList();
 
-    // pointers to all ops within display list, pointing into allocator data
-    std::vector<DisplayListOp*> displayListOps;
-
     // index of DisplayListOp restore, after which projected descendents should be drawn
     int projectionReceiveIndex;
 
-    std::vector<const SkBitmap*> bitmapResources;
-    std::vector<const SkPath*> pathResources;
-    std::vector<const Res_png_9patch*> patchResources;
+    const LsaVector<Chunk>& getChunks() const { return chunks; }
+    const LsaVector<BaseOpType*>& getOps() const { return ops; }
 
-    std::vector<std::unique_ptr<const SkPaint>> paints;
-    std::vector<std::unique_ptr<const SkRegion>> regions;
-    Vector<Functor*> functors;
+    const LsaVector<NodeOpType*>& getChildren() const { return children; }
 
-    const std::vector<Chunk>& getChunks() const {
-            return chunks;
-    }
-    const std::vector<BaseOpType*>& getOps() const {
-        return ops;
-    }
+    const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; }
+    const LsaVector<Functor*>& getFunctors() const { return functors; }
 
     size_t addChild(NodeOpType* childOp);
-    const std::vector<NodeOpType*>& children() { return mChildren; }
+
 
     void ref(VirtualLightRefBase* prop) {
-        mReferenceHolders.push_back(prop);
+        referenceHolders.push_back(prop);
     }
 
     size_t getUsedSize() {
@@ -168,17 +158,27 @@
     }
 
 private:
-    std::vector<BaseOpType*> ops;
-
-    std::vector< sp<VirtualLightRefBase> > mReferenceHolders;
-
-    // list of children display lists for quick, non-drawing traversal
-    std::vector<NodeOpType*> mChildren;
-
-    std::vector<Chunk> chunks;
-
-    // allocator into which all ops were allocated
+    // allocator into which all ops and LsaVector arrays allocated
     LinearAllocator allocator;
+    LinearStdAllocator<void*> stdAllocator;
+
+    LsaVector<Chunk> chunks;
+    LsaVector<BaseOpType*> ops;
+
+    // list of Ops referring to RenderNode children for quick, non-drawing traversal
+    LsaVector<NodeOpType*> children;
+
+    // Resources - Skia objects + 9 patches referred to by this DisplayList
+    LsaVector<const SkBitmap*> bitmapResources;
+    LsaVector<const SkPath*> pathResources;
+    LsaVector<const Res_png_9patch*> patchResources;
+    LsaVector<std::unique_ptr<const SkPaint>> paints;
+    LsaVector<std::unique_ptr<const SkRegion>> regions;
+    LsaVector< sp<VirtualLightRefBase> > referenceHolders;
+
+    // List of functors
+    LsaVector<Functor*> functors;
+
     bool hasDrawOps;
 
     void cleanupResources();
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index f49482b..bad3972 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -82,7 +82,7 @@
 
 void DisplayListCanvas::callDrawGLFunction(Functor *functor) {
     addDrawOp(new (alloc()) DrawFunctorOp(functor));
-    mDisplayList->functors.add(functor);
+    mDisplayList->functors.push_back(functor);
 }
 
 SkCanvas* DisplayListCanvas::asSkCanvas() {
@@ -528,7 +528,7 @@
         newChunk.endOpIndex = insertIndex + 1;
         newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
 
-        int nextChildIndex = mDisplayList->children().size();
+        int nextChildIndex = mDisplayList->children.size();
         newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
         mDeferredBarrierType = kBarrier_None;
     } else {
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/OpReorderer.cpp
index 7c34992..7c0e257 100644
--- a/libs/hwui/OpReorderer.cpp
+++ b/libs/hwui/OpReorderer.cpp
@@ -225,18 +225,17 @@
         if (node->applyViewProperties(mCanvasState)) {
             // not rejected do ops...
             const DisplayList& displayList = node->getDisplayList();
-            deferImpl(displayList.getChunks(), displayList.getOps());
+            deferImpl(displayList);
         }
         mCanvasState.restore();
     }
 }
 
-void OpReorderer::defer(int viewportWidth, int viewportHeight,
-        const std::vector<DisplayList::Chunk>& chunks, const std::vector<RecordedOp*>& ops) {
+void OpReorderer::defer(int viewportWidth, int viewportHeight, const DisplayList& displayList) {
     ATRACE_NAME("prepare drawing commands");
     mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
             0, 0, viewportWidth, viewportHeight, Vector3());
-    deferImpl(chunks, ops);
+    deferImpl(displayList);
 }
 
 /**
@@ -247,14 +246,13 @@
  */
 #define OP_RECIEVER(Type) \
         [](OpReorderer& reorderer, const RecordedOp& op) { reorderer.on##Type(static_cast<const Type&>(op)); },
-void OpReorderer::deferImpl(const std::vector<DisplayList::Chunk>& chunks,
-        const std::vector<RecordedOp*>& ops) {
+void OpReorderer::deferImpl(const DisplayList& displayList) {
     static std::function<void(OpReorderer& reorderer, const RecordedOp&)> receivers[] = {
         MAP_OPS(OP_RECIEVER)
     };
-    for (const DisplayList::Chunk& chunk : chunks) {
+    for (const DisplayList::Chunk& chunk : displayList.getChunks()) {
         for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
-            const RecordedOp* op = ops[opIndex];
+            const RecordedOp* op = displayList.getOps()[opIndex];
             receivers[op->opId](*this, *op);
         }
     }
@@ -288,8 +286,7 @@
     // apply RenderProperties state
     if (op.renderNode->applyViewProperties(mCanvasState)) {
         // not rejected do ops...
-        const DisplayList& displayList = op.renderNode->getDisplayList();
-        deferImpl(displayList.getChunks(), displayList.getOps());
+        deferImpl(op.renderNode->getDisplayList());
     }
     mCanvasState.restore();
 }
diff --git a/libs/hwui/OpReorderer.h b/libs/hwui/OpReorderer.h
index 9c77248..6776a3c 100644
--- a/libs/hwui/OpReorderer.h
+++ b/libs/hwui/OpReorderer.h
@@ -62,8 +62,7 @@
     void defer(const SkRect& clip, int viewportWidth, int viewportHeight,
             const std::vector< sp<RenderNode> >& nodes);
 
-    void defer(int viewportWidth, int viewportHeight,
-            const std::vector<DisplayList::Chunk>& chunks, const std::vector<RecordedOp*>& ops);
+    void defer(int viewportWidth, int viewportHeight, const DisplayList& displayList);
     typedef std::function<void(void*, const RecordedOp&, const BakedOpState&)> BakedOpReceiver;
 
     /**
@@ -92,8 +91,7 @@
 private:
     BakedOpState* bakeOpState(const RecordedOp& recordedOp);
 
-    void deferImpl(const std::vector<DisplayList::Chunk>& chunks,
-            const std::vector<RecordedOp*>& ops);
+    void deferImpl(const DisplayList& displayList);
 
     void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers);
 
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 248a46e..3b413aa 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -369,7 +369,7 @@
         newChunk.endOpIndex = insertIndex + 1;
         newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
 
-        int nextChildIndex = mDisplayList->children().size();
+        int nextChildIndex = mDisplayList->children.size();
         newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
         mDeferredBarrierType = kBarrier_None;
     } else {
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 3d32f02..894a2bd 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -49,7 +49,7 @@
                 mLayer->wasBuildLayered ? "true" : "false");
     }
     if (mDisplayList) {
-        for (auto&& child : mDisplayList->children()) {
+        for (auto&& child : mDisplayList->getChildren()) {
             child->renderNode->debugDumpLayers(prefix);
         }
     }
@@ -178,7 +178,7 @@
 
     pnode->clear_children();
     if (mDisplayList) {
-        for (auto&& child : mDisplayList->children()) {
+        for (auto&& child : mDisplayList->getChildren()) {
             child->renderNode->copyTo(pnode->add_children());
         }
     }
@@ -322,9 +322,9 @@
 
     bool willHaveFunctor = false;
     if (info.mode == TreeInfo::MODE_FULL && mStagingDisplayList) {
-        willHaveFunctor = !mStagingDisplayList->functors.isEmpty();
+        willHaveFunctor = !mStagingDisplayList->getFunctors().empty();
     } else if (mDisplayList) {
-        willHaveFunctor = !mDisplayList->functors.isEmpty();
+        willHaveFunctor = !mDisplayList->getFunctors().empty();
     }
     bool childFunctorsNeedLayer = mProperties.prepareForFunctorPresence(
             willHaveFunctor, functorsNeedLayer);
@@ -379,7 +379,7 @@
     // Make sure we inc first so that we don't fluctuate between 0 and 1,
     // which would thrash the layer cache
     if (mStagingDisplayList) {
-        for (auto&& child : mStagingDisplayList->children()) {
+        for (auto&& child : mStagingDisplayList->getChildren()) {
             child->renderNode->incParentRefCount();
         }
     }
@@ -387,8 +387,8 @@
     mDisplayList = mStagingDisplayList;
     mStagingDisplayList = nullptr;
     if (mDisplayList) {
-        for (size_t i = 0; i < mDisplayList->functors.size(); i++) {
-            (*mDisplayList->functors[i])(DrawGlInfo::kModeSync, nullptr);
+        for (size_t i = 0; i < mDisplayList->getFunctors().size(); i++) {
+            (*mDisplayList->getFunctors()[i])(DrawGlInfo::kModeSync, nullptr);
         }
     }
 }
@@ -406,7 +406,7 @@
 
 void RenderNode::deleteDisplayList() {
     if (mDisplayList) {
-        for (auto&& child : mDisplayList->children()) {
+        for (auto&& child : mDisplayList->getChildren()) {
             child->renderNode->decParentRefCount();
         }
     }
@@ -417,12 +417,11 @@
 void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayList* subtree) {
     if (subtree) {
         TextureCache& cache = Caches::getInstance().textureCache;
-        info.out.hasFunctors |= subtree->functors.size();
-        for (size_t i = 0; info.prepareTextures && i < subtree->bitmapResources.size(); i++) {
-            info.prepareTextures = cache.prefetchAndMarkInUse(
-                    info.canvasContext, subtree->bitmapResources[i]);
+        info.out.hasFunctors |= subtree->getFunctors().size();
+        for (auto&& bitmapResource : subtree->getBitmapResources()) {
+            info.prepareTextures = cache.prefetchAndMarkInUse(info.canvasContext, bitmapResource);
         }
-        for (auto&& op : subtree->children()) {
+        for (auto&& op : subtree->getChildren()) {
             RenderNode* childNode = op->renderNode;
 #if HWUI_NEW_OPS
             info.damageAccumulator->pushTransform(&op->localMatrix);
@@ -445,7 +444,7 @@
         mLayer = nullptr;
     }
     if (mDisplayList) {
-        for (auto&& child : mDisplayList->children()) {
+        for (auto&& child : mDisplayList->getChildren()) {
             child->renderNode->destroyHardwareResources();
         }
         if (mNeedsDisplayListSync) {
@@ -634,8 +633,8 @@
     // TODO: create temporary DDLOp and call computeOrderingImpl on top DisplayList so that
     // transform properties are applied correctly to top level children
     if (mDisplayList == nullptr) return;
-    for (unsigned int i = 0; i < mDisplayList->children().size(); i++) {
-        DrawRenderNodeOp* childOp = mDisplayList->children()[i];
+    for (unsigned int i = 0; i < mDisplayList->getChildren().size(); i++) {
+        DrawRenderNodeOp* childOp = mDisplayList->getChildren()[i];
         childOp->renderNode->computeOrderingImpl(childOp, &mProjectedNodes, &mat4::identity());
     }
 #endif
@@ -664,11 +663,11 @@
         opState->mSkipInOrderDraw = false;
     }
 
-    if (mDisplayList->children().size() > 0) {
+    if (mDisplayList->getChildren().size() > 0) {
         const bool isProjectionReceiver = mDisplayList->projectionReceiveIndex >= 0;
         bool haveAppliedPropertiesToProjection = false;
-        for (unsigned int i = 0; i < mDisplayList->children().size(); i++) {
-            DrawRenderNodeOp* childOp = mDisplayList->children()[i];
+        for (unsigned int i = 0; i < mDisplayList->getChildren().size(); i++) {
+            DrawRenderNodeOp* childOp = mDisplayList->getChildren()[i];
             RenderNode* child = childOp->renderNode;
 
             std::vector<DrawRenderNodeOp*>* projectionChildren = nullptr;
@@ -756,7 +755,7 @@
     if (chunk.beginChildIndex == chunk.endChildIndex) return;
 
     for (unsigned int i = chunk.beginChildIndex; i < chunk.endChildIndex; i++) {
-        DrawRenderNodeOp* childOp = mDisplayList->children()[i];
+        DrawRenderNodeOp* childOp = mDisplayList->getChildren()[i];
         RenderNode* child = childOp->renderNode;
         float childZ = child->properties().getZ();
 
diff --git a/libs/hwui/microbench/DisplayListCanvasBench.cpp b/libs/hwui/microbench/DisplayListCanvasBench.cpp
index 0be7634..7a62037 100644
--- a/libs/hwui/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/microbench/DisplayListCanvasBench.cpp
@@ -23,6 +23,7 @@
 #include "DisplayListCanvas.h"
 #endif
 #include "microbench/MicroBench.h"
+#include "unit_tests/TestUtils.h"
 
 using namespace android;
 using namespace android::uirenderer;
@@ -102,6 +103,40 @@
     StopBenchmarkTiming();
 }
 
+/**
+ * Simulate a simple view drawing a background, overlapped by an image.
+ *
+ * Note that the recording commands are intentionally not perfectly efficient, as the
+ * View system frequently produces unneeded save/restores.
+ */
+BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_simpleBitmapView);
+void BM_DisplayListCanvas_record_simpleBitmapView::Run(int iters) {
+    TestCanvas canvas(100, 100);
+    delete canvas.finishRecording();
+
+    SkPaint rectPaint;
+    SkBitmap iconBitmap = TestUtils::createSkBitmap(80, 80);
+
+    StartBenchmarkTiming();
+    for (int i = 0; i < iters; ++i) {
+        canvas.reset(100, 100);
+        {
+            canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+            canvas.drawRect(0, 0, 100, 100, rectPaint);
+            canvas.restore();
+        }
+        {
+            canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+            canvas.translate(10, 10);
+            canvas.drawBitmap(iconBitmap, 0, 0, nullptr);
+            canvas.restore();
+        }
+        MicroBench::DoNotOptimize(&canvas);
+        delete canvas.finishRecording();
+    }
+    StopBenchmarkTiming();
+}
+
 class NullClient: public CanvasStateClient {
     void onViewportInitialized() override {}
     void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
diff --git a/libs/hwui/unit_tests/OpReordererTests.cpp b/libs/hwui/unit_tests/OpReordererTests.cpp
index 24cff72..e1249fb 100644
--- a/libs/hwui/unit_tests/OpReordererTests.cpp
+++ b/libs/hwui/unit_tests/OpReordererTests.cpp
@@ -49,14 +49,14 @@
     static void endFrame(Info& info) {}
 };
 TEST(OpReorderer, simple) {
-    auto dld = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
         SkBitmap bitmap = TestUtils::createSkBitmap(25, 25);
         canvas.drawRect(0, 0, 100, 200, SkPaint());
         canvas.drawBitmap(bitmap, 10, 10, nullptr);
     });
 
     OpReorderer reorderer;
-    reorderer.defer(200, 200, dld->getChunks(), dld->getOps());
+    reorderer.defer(200, 200, *dl);
 
     Info info;
     reorderer.replayBakedOps<SimpleReceiver>(&info);
@@ -78,7 +78,7 @@
     static void endFrame(Info& info) {}
 };
 TEST(OpReorderer, simpleBatching) {
-    auto dld = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
         SkBitmap bitmap = TestUtils::createSkBitmap(10, 10);
 
         // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
@@ -93,7 +93,7 @@
     });
 
     OpReorderer reorderer;
-    reorderer.defer(200, 200, dld->getChunks(), dld->getOps());
+    reorderer.defer(200, 200, *dl);
 
     Info info;
     reorderer.replayBakedOps<SimpleBatchingReceiver>(&info);
diff --git a/libs/hwui/unit_tests/RecordingCanvasTests.cpp b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
index 7c19df5..ce25fc6 100644
--- a/libs/hwui/unit_tests/RecordingCanvasTests.cpp
+++ b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
@@ -23,30 +23,31 @@
 namespace android {
 namespace uirenderer {
 
-static void playbackOps(const std::vector<DisplayList::Chunk>& chunks,
-        const std::vector<RecordedOp*>& ops, std::function<void(const RecordedOp&)> opReciever) {
-    for (const DisplayList::Chunk& chunk : chunks) {
+static void playbackOps(const DisplayList& displayList,
+        std::function<void(const RecordedOp&)> opReciever) {
+    for (const DisplayList::Chunk& chunk : displayList.getChunks()) {
         for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
-            opReciever(*ops[opIndex]);
+            RecordedOp* op = displayList.getOps()[opIndex];
+            opReciever(*op);
         }
     }
 }
 
 TEST(RecordingCanvas, emptyPlayback) {
-    auto dld = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
         canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
         canvas.restore();
     });
-    playbackOps(dld->getChunks(), dld->getOps(), [](const RecordedOp& op) { FAIL(); });
+    playbackOps(*dl, [](const RecordedOp& op) { FAIL(); });
 }
 
 TEST(RecordingCanvas, testSimpleRectRecord) {
-    auto dld = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
         canvas.drawRect(10, 20, 90, 180, SkPaint());
     });
 
     int count = 0;
-    playbackOps(dld->getChunks(), dld->getOps(), [&count](const RecordedOp& op) {
+    playbackOps(*dl, [&count](const RecordedOp& op) {
         count++;
         ASSERT_EQ(RecordedOpId::RectOp, op.opId);
         ASSERT_EQ(Rect(0, 0, 100, 200), op.localClipRect);
@@ -56,7 +57,7 @@
 }
 
 TEST(RecordingCanvas, backgroundAndImage) {
-    auto dld = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
         SkBitmap bitmap;
         bitmap.setInfo(SkImageInfo::MakeUnknown(25, 25));
         SkPaint paint;
@@ -81,7 +82,7 @@
     });
 
     int count = 0;
-    playbackOps(dld->getChunks(), dld->getOps(), [&count](const RecordedOp& op) {
+    playbackOps(*dl, [&count](const RecordedOp& op) {
         if (count == 0) {
             ASSERT_EQ(RecordedOpId::RectOp, op.opId);
             ASSERT_NE(nullptr, op.paint);
diff --git a/libs/hwui/utils/LinearAllocator.h b/libs/hwui/utils/LinearAllocator.h
index ade4ab3..e1c6f6c 100644
--- a/libs/hwui/utils/LinearAllocator.h
+++ b/libs/hwui/utils/LinearAllocator.h
@@ -29,6 +29,8 @@
 #include <stddef.h>
 #include <type_traits>
 
+#include <vector>
+
 namespace android {
 namespace uirenderer {
 
@@ -175,6 +177,13 @@
 template <class T1, class T2>
 bool operator!= (const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) { return false; }
 
+template <class T>
+class LsaVector : public std::vector<T, LinearStdAllocator<T>> {
+public:
+    LsaVector(const LinearStdAllocator<T>& allocator)
+            : std::vector<T, LinearStdAllocator<T>>(allocator) {}
+};
+
 }; // namespace uirenderer
 }; // namespace android
 
diff --git a/opengl/java/android/opengl/GLUtils.java b/opengl/java/android/opengl/GLUtils.java
index 4d890c9..d097335 100644
--- a/opengl/java/android/opengl/GLUtils.java
+++ b/opengl/java/android/opengl/GLUtils.java
@@ -261,12 +261,6 @@
         }
     }
 
-    /**
-     * Set OpenGL Tracing level for this application.
-     * @hide
-     */
-    native public static void setTracingLevel(int level);
-
     native private static int native_getInternalFormat(Bitmap bitmap);
     native private static int native_getType(Bitmap bitmap);
     native private static int native_texImage2D(int target, int level, int internalformat,
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index ed7820b..73538278 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -16,4 +16,6 @@
 
 <resources>
     <bool name="productivity_device">true</bool>
+    <!-- intentionally unset. Vendors should set this in an overlay. -->
+    <string name="trusted_quick_viewer_package"></string>
 </resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 83e3440..e3b1324 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -466,25 +466,6 @@
         }
     }
 
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (DEBUG) Log.d(mTag, "onKeyUp: keycode = " + keyCode);
-
-        // TODO: Support for RecentsCreateFragment.
-        DirectoryFragment fragment = DirectoryFragment.get(getFragmentManager());
-        if (fragment != null) {
-            switch (keyCode) {
-                case KeyEvent.KEYCODE_MOVE_HOME:
-                    fragment.focusFirstFile();
-                    return true;
-                case KeyEvent.KEYCODE_MOVE_END:
-                    fragment.focusLastFile();
-                    return true;
-            }
-        }
-        return super.onKeyUp(keyCode, event);
-    }
-
     public void onStackPicked(DocumentStack stack) {
         try {
             // Update the restored stack to ensure we have freshest data
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index a3a431f..7662689 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -17,7 +17,6 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.Shared.TAG;
 import static com.android.documentsui.State.ACTION_BROWSE;
 import static com.android.documentsui.State.ACTION_CREATE;
 import static com.android.documentsui.State.ACTION_MANAGE;
@@ -66,6 +65,7 @@
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.LayoutManager;
+import android.support.v7.widget.RecyclerView.OnItemTouchListener;
 import android.support.v7.widget.RecyclerView.RecyclerListener;
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.text.TextUtils;
@@ -109,6 +109,8 @@
  */
 public class DirectoryFragment extends Fragment {
 
+    public static final String TAG = "DirectoryFragment";
+
     public static final int TYPE_NORMAL = 1;
     public static final int TYPE_SEARCH = 2;
     public static final int TYPE_RECENT_OPEN = 3;
@@ -130,6 +132,7 @@
     private static final String EXTRA_IGNORE_STATE = "ignoreState";
 
     private Model mModel;
+    private MultiSelectManager mSelectionManager;
     private Model.UpdateListener mModelUpdateListener = new ModelUpdateListener();
 
     private View mEmptyView;
@@ -268,7 +271,7 @@
         }
 
         // Clear any outstanding selection
-        mModel.clearSelection();
+        mSelectionManager.clearSelection();
     }
 
     @Override
@@ -297,18 +300,35 @@
                     }
                 };
 
+        final GestureDetector detector = new GestureDetector(this.getContext(), listener);
+        detector.setOnDoubleTapListener(listener);
+
+        mRecView.addOnItemTouchListener(
+                new OnItemTouchListener() {
+                    @Override
+                    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+                        detector.onTouchEvent(e);
+                        return false;
+                    }
+
+                    @Override
+                    public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
+
+                    @Override
+                    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
+                });
+
         // TODO: instead of inserting the view into the constructor, extract listener-creation code
         // and set the listener on the view after the fact.  Then the view doesn't need to be passed
-        // into the selection manager which is passed into the model.
-        MultiSelectManager selMgr= new MultiSelectManager(
+        // into the selection manager.
+        mSelectionManager = new MultiSelectManager(
                 mRecView,
-                listener,
                 state.allowMultiple
                     ? MultiSelectManager.MODE_MULTIPLE
                     : MultiSelectManager.MODE_SINGLE);
-        selMgr.addCallback(new SelectionModeListener());
+        mSelectionManager.addCallback(new SelectionModeListener());
 
-        mModel = new Model(context, selMgr, mAdapter);
+        mModel = new Model(context, mAdapter);
         mModel.addUpdateListener(mModelUpdateListener);
 
         mType = getArguments().getInt(EXTRA_TYPE);
@@ -430,7 +450,7 @@
     }
 
     private boolean onSingleTapUp(MotionEvent e) {
-        if (Events.isTouchEvent(e) && mModel.getSelection().isEmpty()) {
+        if (Events.isTouchEvent(e) && mSelectionManager.getSelection().isEmpty()) {
             int position = getEventAdapterPosition(e);
             if (position != RecyclerView.NO_POSITION) {
                 return handleViewItem(position);
@@ -458,7 +478,7 @@
         if (isDocumentEnabled(docMimeType, docFlags)) {
             final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
             ((BaseActivity) getActivity()).onDocumentPicked(doc, mModel);
-            mModel.clearSelection();
+            mSelectionManager.clearSelection();
             return true;
         }
         return false;
@@ -564,7 +584,7 @@
         mRecView.setLayoutManager(layout);
         // TODO: Once b/23691541 is resolved, use a listener within MultiSelectManager instead of
         // imperatively calling this function.
-        mModel.mSelectionManager.handleLayoutChanged();
+        mSelectionManager.handleLayoutChanged();
         // setting layout manager automatically invalidates existing ViewHolders.
         mThumbSize = new Point(thumbSize, thumbSize);
     }
@@ -620,7 +640,7 @@
 
         @Override
         public void onSelectionChanged() {
-            mModel.getSelection(mSelected);
+            mSelectionManager.getSelection(mSelected);
             TypedValue color = new TypedValue();
             if (mSelected.size() > 0) {
                 if (DEBUG) Log.d(TAG, "Maybe starting action mode.");
@@ -628,8 +648,7 @@
                     if (DEBUG) Log.d(TAG, "Yeah. Starting action mode.");
                     mActionMode = getActivity().startActionMode(this);
                 }
-                getActivity().getTheme().resolveAttribute(
-                    R.attr.colorActionMode, color, true);
+                getActivity().getTheme().resolveAttribute(R.attr.colorActionMode, color, true);
                 updateActionMenu();
             } else {
                 if (DEBUG) Log.d(TAG, "Finishing action mode.");
@@ -652,16 +671,17 @@
             if (DEBUG) Log.d(TAG, "Handling action mode destroyed.");
             mActionMode = null;
             // clear selection
-            mModel.clearSelection();
+            mSelectionManager.clearSelection();
             mSelected.clear();
             mNoDeleteCount = 0;
         }
 
         @Override
         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+            int size = mSelectionManager.getSelection().size();
             mode.getMenuInflater().inflate(R.menu.mode_directory, menu);
-            mode.setTitle(TextUtils.formatSelectedCount(mModel.getSelection().size()));
-            return mModel.getSelection().size() > 0;
+            mode.setTitle(TextUtils.formatSelectedCount(size));
+            return (size > 0);
         }
 
         @Override
@@ -681,7 +701,7 @@
         @Override
         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
 
-            Selection selection = mModel.getSelection(new Selection());
+            Selection selection = mSelectionManager.getSelection(new Selection());
 
             final int id = item.getItemId();
             if (id == R.id.menu_open) {
@@ -920,15 +940,22 @@
         public DocumentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
             final State state = getDisplayState(DirectoryFragment.this);
             final LayoutInflater inflater = LayoutInflater.from(getContext());
+            View item = null;
             switch (state.derivedMode) {
                 case MODE_GRID:
-                    return new DocumentHolder(inflater.inflate(R.layout.item_doc_grid, parent, false));
+                    item = inflater.inflate(R.layout.item_doc_grid, parent, false);
+                    break;
                 case MODE_LIST:
-                    return new DocumentHolder(inflater.inflate(R.layout.item_doc_list, parent, false));
+                    item = inflater.inflate(R.layout.item_doc_list, parent, false);
+                    break;
                 case MODE_UNKNOWN:
                 default:
                     throw new IllegalStateException("Unsupported layout mode.");
             }
+            // Key event bubbling doesn't work properly, so instead of setting one key listener on
+            // the RecyclerView, we have to set it on each Item.  See b/24865023.
+            item.setOnKeyListener(mSelectionManager);
+            return new DocumentHolder(item);
         }
 
         @Override
@@ -957,7 +984,7 @@
 
             holder.docId = docId;
             final View itemView = holder.view;
-            itemView.setActivated(mModel.isSelected(position));
+            itemView.setActivated(isSelected(position));
 
             final View line1 = itemView.findViewById(R.id.line1);
             final View line2 = itemView.findViewById(R.id.line2);
@@ -1289,7 +1316,7 @@
     }
 
     void copySelectedToClipboard() {
-        Selection sel = mModel.getSelection(new Selection());
+        Selection sel = mSelectionManager.getSelection(new Selection());
         copySelectionToClipboard(sel);
     }
 
@@ -1338,51 +1365,12 @@
     }
 
     void selectAllFiles() {
-        boolean changed = mModel.selectAll();
+        boolean changed = mSelectionManager.setItemsSelected(0, mModel.getItemCount(), true);
         if (changed) {
             updateDisplayState();
         }
     }
 
-    /**
-     * Scrolls to the top of the file list and focuses the first file.
-     */
-    void focusFirstFile() {
-        focusFile(0);
-    }
-
-    /**
-     * Scrolls to the bottom of the file list and focuses the last file.
-     */
-    void focusLastFile() {
-        focusFile(mAdapter.getItemCount() - 1);
-    }
-
-    /**
-     * Scrolls to and then focuses on the file at the given position.
-     */
-    private void focusFile(final int pos) {
-        // Don't smooth scroll; that taxes the system unnecessarily and makes the scroll handling
-        // logic below more complicated.
-        mRecView.scrollToPosition(pos);
-
-        // If the item is already in view, focus it; otherwise, set a one-time listener to focus it
-        // when the scroll is completed.
-        RecyclerView.ViewHolder vh = mRecView.findViewHolderForAdapterPosition(pos);
-        if (vh != null) {
-            vh.itemView.requestFocus();
-        } else {
-            mRecView.addOnScrollListener(
-                    new RecyclerView.OnScrollListener() {
-                        @Override
-                        public void onScrolled(RecyclerView view, int dx, int dy) {
-                            view.findViewHolderForAdapterPosition(pos).itemView.requestFocus();
-                            view.removeOnScrollListener(this);
-                        }
-                    });
-        }
-    }
-
     private void setupDragAndDropOnDirectoryView(View view) {
         // Listen for drops on non-directory items and empty space.
         view.setOnDragListener(mOnDragListener);
@@ -1472,9 +1460,10 @@
             return Collections.EMPTY_LIST;
         }
 
-        final List<DocumentInfo> selectedDocs = mModel.getSelectedDocuments();
+        final List<DocumentInfo> selectedDocs =
+                mModel.getDocuments(mSelectionManager.getSelection());
         if (!selectedDocs.isEmpty()) {
-            if (!mModel.isSelected(position)) {
+            if (!isSelected(position)) {
                 // There is a selection that does not include the current item, drag nothing.
                 return Collections.EMPTY_LIST;
             }
@@ -1694,12 +1683,15 @@
         public void afterActivityCreated(DirectoryFragment fragment) {}
     }
 
+    boolean isSelected(int position) {
+        return mSelectionManager.getSelection().contains(position);
+    }
+
     /**
      * The data model for the current loaded directory.
      */
     @VisibleForTesting
     public static final class Model implements DocumentContext {
-        private MultiSelectManager mSelectionManager;
         private RecyclerView.Adapter<?> mViewAdapter;
         private Context mContext;
         private int mCursorCount;
@@ -1710,45 +1702,11 @@
         @Nullable private String info;
         @Nullable private String error;
 
-        Model(Context context, MultiSelectManager selectionManager,
-                RecyclerView.Adapter<?> viewAdapter) {
+        Model(Context context, RecyclerView.Adapter<?> viewAdapter) {
             mContext = context;
-            mSelectionManager = selectionManager;
             mViewAdapter = viewAdapter;
         }
 
-        /**
-         * Selects all files in the current directory.
-         * @return true if the selection state changed for any files.
-         */
-        boolean selectAll() {
-            return mSelectionManager.setItemsSelected(0, mCursorCount, true);
-        }
-
-        /**
-         * Clones the current selection into the given Selection object.
-         * @param selection
-         * @return The selection that was passed in, for convenience.
-         */
-        Selection getSelection(Selection selection) {
-            return mSelectionManager.getSelection(selection);
-        }
-
-        /**
-         * @return The current selection (the live instance, not a copy).
-         */
-        Selection getSelection() {
-            return mSelectionManager.getSelection();
-        }
-
-        boolean isSelected(int position) {
-            return mSelectionManager.getSelection().contains(position);
-        }
-
-        void clearSelection() {
-            mSelectionManager.clearSelection();
-        }
-
         void update(DirectoryResult result) {
             if (DEBUG) Log.i(TAG, "Updating model with new result set.");
 
@@ -1821,11 +1779,6 @@
             return mIsLoading;
         }
 
-        private List<DocumentInfo> getSelectedDocuments() {
-            Selection sel = getSelection(new Selection());
-            return getDocuments(sel);
-        }
-
         List<DocumentInfo> getDocuments(Selection items) {
             final int size = (items != null) ? items.size() : 0;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 1330b3c..3b985ec 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -323,26 +323,36 @@
     private void openDocument(DocumentInfo doc, @Nullable DocumentContext siblings) {
         Intent intent = null;
         if (siblings != null) {
-            QuickViewIntentBuilder builder =
-                    new QuickViewIntentBuilder(getPackageManager(), doc, siblings);
+            QuickViewIntentBuilder builder = new QuickViewIntentBuilder(
+                    getPackageManager(), getResources(), doc, siblings);
             intent = builder.build();
         }
 
-        // fallback to traditional VIEW action...
-        if (intent == null) {
-            intent = new Intent(Intent.ACTION_VIEW);
-            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-            intent.setData(doc.derivedUri);
+        if (intent != null) {
+            // TODO: un-work around issue b/24963914. Should be fixed soon.
+            try {
+                startActivity(intent);
+                return;
+            } catch (SecurityException e) {
+                // carry on to regular view mode.
+                Log.e(TAG, "Caught security error: " + e.getLocalizedMessage());
+            }
         }
 
+        // fallback to traditional VIEW action...
+        intent = new Intent(Intent.ACTION_VIEW);
+        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        intent.setData(doc.derivedUri);
+
         if (DEBUG && intent.getClipData() != null) {
             Log.d(TAG, "Starting intent w/ clip data: " + intent.getClipData());
         }
 
         try {
             startActivity(intent);
-        } catch (ActivityNotFoundException ex2) {
-            Snackbars.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT).show();
+        } catch (ActivityNotFoundException e) {
+            Snackbars.makeSnackbar(
+                    this, R.string.toast_no_application, Snackbar.LENGTH_SHORT).show();
         }
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
index 858fb42..87c037d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
@@ -37,16 +37,13 @@
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 import android.view.GestureDetector;
-import android.view.GestureDetector.OnDoubleTapListener;
-import android.view.GestureDetector.OnGestureListener;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 
 import com.android.documentsui.Events.InputEvent;
 import com.android.documentsui.Events.MotionInputEvent;
 
-import com.google.android.collect.Lists;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -56,7 +53,7 @@
  * Additionally it can be configured to restrict selection to a single element, @see
  * #setSelectMode.
  */
-public final class MultiSelectManager {
+public final class MultiSelectManager implements View.OnKeyListener {
 
     /** Selection mode for multiple select. **/
     public static final int MODE_MULTIPLE = 0;
@@ -72,33 +69,26 @@
     private Selection mIntermediateSelection;
 
     private Range mRanger;
+    private SelectionEnvironment mEnvironment;
+
     private final List<MultiSelectManager.Callback> mCallbacks = new ArrayList<>(1);
 
     private Adapter<?> mAdapter;
-    private ItemFinder mHelper;
     private boolean mSingleSelect;
 
     @Nullable private BandController mBandManager;
 
     /**
      * @param recyclerView
-     * @param gestureDelegate Option delegate gesture listener.
      * @param mode Selection mode
-     * @template A gestureDelegate that implements both {@link OnGestureListener}
-     *     and {@link OnDoubleTapListener}
      */
-    public <L extends OnGestureListener & OnDoubleTapListener> MultiSelectManager(
-            final RecyclerView recyclerView, L gestureDelegate, int mode) {
+    public MultiSelectManager(final RecyclerView recyclerView, int mode) {
+        this(recyclerView.getAdapter(), mode);
 
-        this(
-                recyclerView.getAdapter(),
-                new RuntimeItemFinder(recyclerView),
-                mode);
+        mEnvironment = new RuntimeSelectionEnvironment(recyclerView);
 
         if (mode == MODE_MULTIPLE) {
-            mBandManager = new BandController(
-                    mHelper,
-                    new RuntimeBandEnvironment(recyclerView));
+            mBandManager = new BandController();
         }
 
         GestureDetector.SimpleOnGestureListener listener =
@@ -115,15 +105,8 @@
                     }
                 };
 
-        CompositeOnGestureListener compositeListener =
-                new CompositeOnGestureListener(
-                        Lists.<OnGestureListener>newArrayList(listener, gestureDelegate),
-                        Lists.<OnDoubleTapListener>newArrayList(listener, gestureDelegate));
-
-        final GestureDetector detector =
-                new GestureDetector(recyclerView.getContext(), compositeListener);
-
-        detector.setOnDoubleTapListener(compositeListener);
+        final GestureDetector detector = new GestureDetector(recyclerView.getContext(), listener);
+        detector.setOnDoubleTapListener(listener);
 
         recyclerView.addOnItemTouchListener(
                 new RecyclerView.OnItemTouchListener() {
@@ -131,37 +114,15 @@
                     public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                         detector.onTouchEvent(e);
 
-                        if (mBandManager == null) {
-                            return false;
+                        if (mBandManager != null) {
+                            return mBandManager.handleEvent(new MotionInputEvent(e, recyclerView));
                         }
-
-                        // b/23793622 notes the fact that we *never* receiver ACTION_DOWN
-                        // events in onTouchEvent. Where it not for this issue, we'd
-                        // push start handling down into handleInputEvent.
-                        if (mBandManager.shouldStart(e)) {
-                            // endBandSelect is handled in handleInputEvent.
-                            mBandManager.startBandSelect(
-                                    new Point((int) e.getX(), (int) e.getY()));
-                        } else if (mBandManager.isActive()
-                                && Events.isMouseEvent(e)
-                                && Events.isActionUp(e)) {
-                            // Same issue here w b/23793622. The ACTION_UP event
-                            // is only evert dispatched to onTouchEvent when
-                            // there is some associated motion. If a user taps
-                            // mouse, but doesn't move, then band select gets
-                            // started BUT not ended. Causing phantom
-                            // bands to appear when the user later clicks to start
-                            // band select.
-                            mBandManager.handleInputEvent(
-                                    new MotionInputEvent(e, recyclerView));
-                        }
-
-                        return mBandManager.isActive();
+                        return false;
                     }
 
                     @Override
                     public void onTouchEvent(RecyclerView rv, MotionEvent e) {
-                        mBandManager.handleInputEvent(
+                        mBandManager.processInputEvent(
                                 new MotionInputEvent(e, recyclerView));
                     }
                     @Override
@@ -174,13 +135,11 @@
      * @hide
      */
     @VisibleForTesting
-    MultiSelectManager(Adapter<?> adapter, ItemFinder helper, int mode) {
+    MultiSelectManager(Adapter<?> adapter, int mode) {
         checkNotNull(adapter, "'adapter' cannot be null.");
-        checkNotNull(helper, "'helper' cannot be null.");
 
         mSingleSelect = mode == MODE_SINGLE;
 
-        mHelper = helper;
         mAdapter = adapter;
 
         mAdapter.registerAdapterDataObserver(
@@ -871,36 +830,10 @@
     }
 
     /**
-     * Provides functionality for MultiSelectManager. Exists primarily to tests that are
-     * fully isolated from RecyclerView.
-     */
-    interface ItemFinder {
-        int findItemPosition(MotionEvent e);
-    }
-
-    /** ItemFinder implementation backed by good ol' RecyclerView. */
-    private static final class RuntimeItemFinder implements ItemFinder {
-
-        private final RecyclerView mView;
-
-        RuntimeItemFinder(RecyclerView view) {
-            mView = view;
-        }
-
-        @Override
-        public int findItemPosition(MotionEvent e) {
-            View view = mView.findChildViewUnder(e.getX(), e.getY());
-            return view != null
-                    ? mView.getChildAdapterPosition(view)
-                    : RecyclerView.NO_POSITION;
-        }
-    }
-
-    /**
      * Provides functionality for BandController. Exists primarily to tests that are
      * fully isolated from RecyclerView.
      */
-    interface BandEnvironment {
+    interface SelectionEnvironment {
         void showBand(Rect rect);
         void hideBand();
         void addOnScrollListener(RecyclerView.OnScrollListener listener);
@@ -913,29 +846,39 @@
         Point createAbsolutePoint(Point relativePoint);
         Rect getAbsoluteRectForChildViewAt(int index);
         int getAdapterPositionAt(int index);
+        int getAdapterPositionForChildView(View view);
         int getColumnCount();
         int getRowCount();
         int getChildCount();
         int getVisibleChildCount();
+        void focusItem(int position);
     }
 
     /** RvFacade implementation backed by good ol' RecyclerView. */
-    private static final class RuntimeBandEnvironment implements BandEnvironment {
+    private static final class RuntimeSelectionEnvironment implements SelectionEnvironment {
 
         private final RecyclerView mView;
         private final Drawable mBand;
 
         private boolean mIsOverlayShown = false;
 
-        RuntimeBandEnvironment(RecyclerView rv) {
+        RuntimeSelectionEnvironment(RecyclerView rv) {
             mView = rv;
             mBand = mView.getContext().getTheme().getDrawable(R.drawable.band_select_overlay);
         }
 
         @Override
+        public int getAdapterPositionForChildView(View view) {
+            if (view.getParent() == mView) {
+                return mView.getChildAdapterPosition(view);
+            } else {
+                return RecyclerView.NO_POSITION;
+            }
+        }
+
+        @Override
         public int getAdapterPositionAt(int index) {
-            View child = mView.getChildAt(index);
-            return mView.getChildViewHolder(child).getAdapterPosition();
+            return getAdapterPositionForChildView(mView.getChildAt(index));
         }
 
         @Override
@@ -1032,6 +975,28 @@
         public void hideBand() {
             mView.getOverlay().remove(mBand);
         }
+
+        @Override
+        public void focusItem(final int pos) {
+            // If the item is already in view, focus it; otherwise, scroll to it and focus it.
+            RecyclerView.ViewHolder vh = mView.findViewHolderForAdapterPosition(pos);
+            if (vh != null) {
+                vh.itemView.requestFocus();
+            } else {
+                // Don't smooth scroll; that taxes the system unnecessarily and makes the scroll
+                // handling logic below more complicated.  See b/24865658.
+                mView.scrollToPosition(pos);
+                // Set a one-time listener to request focus when the scroll has completed.
+                mView.addOnScrollListener(
+                    new RecyclerView.OnScrollListener() {
+                        @Override
+                        public void onScrolled(RecyclerView view, int dx, int dy) {
+                            view.findViewHolderForAdapterPosition(pos).itemView.requestFocus();
+                            view.removeOnScrollListener(this);
+                        }
+                    });
+            }
+        }
     }
 
     public interface Callback {
@@ -1061,110 +1026,6 @@
     }
 
     /**
-     * A composite {@code OnGestureDetector} that allows us to delegate unhandled
-     * events to an outside party (presumably DirectoryFragment).
-     * @template A gestureDelegate that implements both {@link OnGestureListener}
-     *     and {@link OnDoubleTapListener}
-     */
-    private static final class CompositeOnGestureListener
-            implements OnGestureListener, OnDoubleTapListener {
-
-        private List<OnGestureListener> mGestureListeners;
-        private List<OnDoubleTapListener> mTapListeners;
-
-        public CompositeOnGestureListener(
-                List<OnGestureListener> gestureListeners,
-                List<OnDoubleTapListener> tapListeners) {
-            mGestureListeners = gestureListeners;
-            mTapListeners = tapListeners;
-        }
-
-        @Override
-        public boolean onDown(MotionEvent e) {
-            for (OnGestureListener l : mGestureListeners) {
-                if (l.onDown(e)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public void onShowPress(MotionEvent e) {
-            for (OnGestureListener l : mGestureListeners) {
-                l.onShowPress(e);
-            }
-        }
-
-        @Override
-        public boolean onSingleTapUp(MotionEvent e) {
-            for (OnGestureListener l : mGestureListeners) {
-                if (l.onSingleTapUp(e)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
-            for (OnGestureListener l : mGestureListeners) {
-                if (l.onScroll(e1, e2, distanceX, distanceY)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public void onLongPress(MotionEvent e) {
-            for (OnGestureListener l : mGestureListeners) {
-                l.onLongPress(e);
-            }
-        }
-
-        @Override
-        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
-            for (OnGestureListener l : mGestureListeners) {
-                if (l.onFling(e1, e2, velocityX, velocityY)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public boolean onSingleTapConfirmed(MotionEvent e) {
-            for (OnDoubleTapListener listener : mTapListeners) {
-                if (listener.onSingleTapConfirmed(e)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public boolean onDoubleTap(MotionEvent e) {
-            for (OnDoubleTapListener listener : mTapListeners) {
-                if (listener.onDoubleTap(e)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public boolean onDoubleTapEvent(MotionEvent e) {
-            for (OnDoubleTapListener listener : mTapListeners) {
-                if (listener.onDoubleTapEvent(e)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
-    /**
      * Provides mouse driven band-select support when used in conjunction with {@link RecyclerView}
      * and {@link MultiSelectManager}. This class is responsible for rendering the band select
      * overlay and selecting overlaid items via MultiSelectManager.
@@ -1174,8 +1035,6 @@
 
         private static final int NOT_SET = -1;
 
-        private final ItemFinder mItemFinder;
-        private final BandEnvironment mEnvironment;
         private final Runnable mModelBuilder;
 
         @Nullable private Rect mBounds;
@@ -1188,20 +1047,41 @@
         private long mScrollStartTime = NOT_SET;
         private final Runnable mViewScroller = new ViewScroller();
 
-        public BandController(ItemFinder finder, final BandEnvironment environment) {
-            mItemFinder = finder;
-            mEnvironment = environment;
+        public BandController() {
             mEnvironment.addOnScrollListener(this);
 
             mModelBuilder = new Runnable() {
                 @Override
                 public void run() {
-                    mModel = new GridModel(environment);
+                    mModel = new GridModel(mEnvironment);
                     mModel.addOnSelectionChangedListener(BandController.this);
                 }
             };
         }
 
+        public boolean handleEvent(MotionInputEvent e) {
+            // b/23793622 notes the fact that we *never* receive ACTION_DOWN
+            // events in onTouchEvent. Where it not for this issue, we'd
+            // push start handling down into handleInputEvent.
+            if (mBandManager.shouldStart(e)) {
+                // endBandSelect is handled in handleInputEvent.
+                mBandManager.startBandSelect(e.getOrigin());
+            } else if (mBandManager.isActive()
+                    && e.isMouseEvent()
+                    && e.isActionUp()) {
+                // Same issue here w b/23793622. The ACTION_UP event
+                // is only evert dispatched to onTouchEvent when
+                // there is some associated motion. If a user taps
+                // mouse, but doesn't move, then band select gets
+                // started BUT not ended. Causing phantom
+                // bands to appear when the user later clicks to start
+                // band select.
+                mBandManager.processInputEvent(e);
+            }
+
+            return isActive();
+        }
+
         private boolean isActive() {
             return mModel != null;
         }
@@ -1220,12 +1100,12 @@
             }
         }
 
-        boolean shouldStart(MotionEvent e) {
+        boolean shouldStart(MotionInputEvent e) {
             return !isActive()
-                    && Events.isMouseEvent(e)  // a mouse
-                    && Events.isActionDown(e)  // the initial button press
+                    && e.isMouseEvent()  // a mouse
+                    && e.isActionDown()  // the initial button press
                     && mAdapter.getItemCount() > 0
-                    && mItemFinder.findItemPosition(e) == RecyclerView.NO_ID;  // in empty space
+                    && e.getItemPosition() == RecyclerView.NO_ID;  // in empty space
         }
 
         boolean shouldStop(InputEvent input) {
@@ -1238,7 +1118,7 @@
          * Processes a MotionEvent by starting, ending, or resizing the band select overlay.
          * @param input
          */
-        private void handleInputEvent(InputEvent input) {
+        private void processInputEvent(InputEvent input) {
             checkArgument(input.isMouseEvent());
 
             if (shouldStop(input)) {
@@ -1459,7 +1339,7 @@
         private static final int LOWER_LEFT = LOWER | LEFT;
         private static final int LOWER_RIGHT = LOWER | RIGHT;
 
-        private final BandEnvironment mHelper;
+        private final SelectionEnvironment mHelper;
         private final List<OnSelectionChangedListener> mOnSelectionChangedListeners =
                 new ArrayList<>();
 
@@ -1497,7 +1377,7 @@
         // should expand from when Shift+click is used.
         private int mPositionNearestOrigin = NOT_SET;
 
-        GridModel(BandEnvironment helper) {
+        GridModel(SelectionEnvironment helper) {
             mHelper = helper;
             mHelper.addOnScrollListener(this);
         }
@@ -2041,4 +1921,72 @@
             return true;
         }
     }
+
+    // TODO: Might have to move this to a more global level.  e.g. What should happen if the
+    // user taps a file and then presses shift-down?  Currently the RecyclerView never even sees
+    // the key event.  Perhaps install a global key handler to catch those events while in
+    // selection mode?
+    @Override
+    public boolean onKey(View view, int keyCode, KeyEvent event) {
+        // Listen for key-down events.  This allows the handler to respond appropriately when
+        // the user holds down the arrow keys for navigation.
+        if (event.getAction() != KeyEvent.ACTION_DOWN) {
+            return false;
+        }
+
+        int target = RecyclerView.NO_POSITION;
+        if (keyCode == KeyEvent.KEYCODE_MOVE_HOME) {
+            target = 0;
+        } else if (keyCode == KeyEvent.KEYCODE_MOVE_END) {
+            target = mAdapter.getItemCount() - 1;
+        } else {
+            // Find a navigation target based on the arrow key that the user pressed.  Ignore
+            // navigation targets that aren't items in the recycler view.
+            int searchDir = -1;
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_DPAD_UP:
+                    searchDir = View.FOCUS_UP;
+                    break;
+                case KeyEvent.KEYCODE_DPAD_DOWN:
+                    searchDir = View.FOCUS_DOWN;
+                    break;
+                case KeyEvent.KEYCODE_DPAD_LEFT:
+                    searchDir = View.FOCUS_LEFT;
+                    break;
+                case KeyEvent.KEYCODE_DPAD_RIGHT:
+                    searchDir = View.FOCUS_RIGHT;
+                    break;
+            }
+            if (searchDir != -1) {
+                View targetView = view.focusSearch(searchDir);
+                target = mEnvironment.getAdapterPositionForChildView(targetView);
+            }
+        }
+
+        if (target == RecyclerView.NO_POSITION) {
+            // If there is no valid navigation target, don't handle the keypress.
+            return false;
+        }
+
+        // Focus the new file.
+        mEnvironment.focusItem(target);
+
+        if (event.isShiftPressed()) {
+            if (mSelection.isEmpty()) {
+                // If there is no selection, start a selection when the user presses shift-arrow.
+                toggleSelection(mEnvironment.getAdapterPositionForChildView(view));
+            } else {
+                // Deal with b/24802917 (selected items can't be focused) by adjusting the
+                // selection sorted the focused item isn't in the selection.
+                target -= Integer.signum(target - mRanger.mBegin);
+                mRanger.snapSelection(target);
+            }
+        } else if (!event.isShiftPressed() && !mSelection.isEmpty()) {
+            // If there is a selection, clear it if the user presses arrow with no shift.
+            clearSelection();
+        }
+
+        return true;
+    }
+
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
index 607cb95..6a424a6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
@@ -25,11 +25,13 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.support.annotation.Nullable;
+import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.documentsui.BaseActivity.DocumentContext;
@@ -43,13 +45,20 @@
     private final DocumentInfo mDocument;
     private final DocumentContext mContext;
 
-    public ClipData mClipData;
-    public int mDocumentLocation;
-    private PackageManager mPkgManager;
+    private final PackageManager mPkgManager;
+    private final Resources mResources;
+
+    private ClipData mClipData;
+    private int mDocumentLocation;
 
     public QuickViewIntentBuilder(
-            PackageManager pkgManager, DocumentInfo doc, DocumentContext context) {
+            PackageManager pkgManager,
+            Resources resources,
+            DocumentInfo doc,
+            DocumentContext context) {
+
         mPkgManager = pkgManager;
+        mResources = resources;
         mDocument = doc;
         mContext = context;
     }
@@ -61,25 +70,37 @@
     @Nullable Intent build() {
         if (DEBUG) Log.d(TAG, "Preparing intent for doc:" + mDocument.documentId);
 
+        String trustedPkg = mResources.getString(R.string.trusted_quick_viewer_package);
+
         Intent intent = new Intent(Intent.ACTION_QUICK_VIEW);
         intent.setDataAndType(mDocument.derivedUri, mDocument.mimeType);
-
-        // Try to resolve the intent. If a matching app isn't installed, it won't resolve.
-        ComponentName handler = intent.resolveActivity(mPkgManager);
-        if (handler == null) {
-            return null;
-        }
-
-        Cursor cursor = mContext.getCursor();
-        for (int i = 0; i < cursor.getCount(); i++) {
-            onNextItem(i, cursor);
-        }
-
         intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        intent.putExtra(Intent.EXTRA_INDEX, mDocumentLocation);
-        intent.setClipData(mClipData);
 
-        return intent;
+        if (TextUtils.isEmpty(trustedPkg)) {
+            if (hasRegisteredHandler(intent)) {
+                return intent;
+            }
+        } else {
+            intent.setPackage(trustedPkg);
+            if (hasRegisteredHandler(intent)) {
+                // We have a trusted handler. Load all of the docs into the intent.
+                Cursor cursor = mContext.getCursor();
+                for (int i = 0; i < cursor.getCount(); i++) {
+                    onNextItem(i, cursor);
+                }
+                intent.putExtra(Intent.EXTRA_INDEX, mDocumentLocation);
+                intent.setClipData(mClipData);
+
+                return intent;
+            }
+        }
+
+        return null;
+    }
+
+    private boolean hasRegisteredHandler(Intent intent) {
+        // Try to resolve the intent. If a matching app isn't installed, it won't resolve.
+        return intent.resolveActivity(mPkgManager) != null;
     }
 
     private void onNextItem(int index, Cursor cursor) {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
index 98ffb77..ace9e27 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DirectoryFragmentModelTest.java
@@ -22,10 +22,8 @@
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.provider.DocumentsContract.Document;
-import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.support.v7.widget.RecyclerView;
 import android.test.AndroidTestCase;
-import android.test.MoreAsserts;
 import android.test.mock.MockContentResolver;
 import android.view.ViewGroup;
 
@@ -64,7 +62,7 @@
         r.cursor = cursor;
 
         // Instantiate the model with a dummy view adapter and listener that (for now) do nothing.
-        model = new Model(mContext, null, new DummyAdapter());
+        model = new Model(mContext, new DummyAdapter());
         model.addUpdateListener(new DummyListener());
         model.update(r);
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
index 2447469..ceb8cdc 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
@@ -16,13 +16,9 @@
 
 package com.android.documentsui;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
 import android.support.v7.widget.RecyclerView;
 import android.test.AndroidTestCase;
 import android.util.SparseBooleanArray;
-import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -51,13 +47,11 @@
     private MultiSelectManager mManager;
     private TestAdapter mAdapter;
     private TestCallback mCallback;
-    private EventHelper mEventHelper;
 
     public void setUp() throws Exception {
         mAdapter = new TestAdapter(items);
         mCallback = new TestCallback();
-        mEventHelper = new EventHelper();
-        mManager = new MultiSelectManager(mAdapter, mEventHelper, MultiSelectManager.MODE_MULTIPLE);
+        mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_MULTIPLE);
         mManager.addCallback(mCallback);
     }
 
@@ -175,7 +169,7 @@
     }
 
     public void testSingleSelectMode() {
-        mManager = new MultiSelectManager(mAdapter, mEventHelper, MultiSelectManager.MODE_SINGLE);
+        mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_SINGLE);
         mManager.addCallback(mCallback);
         longPress(20);
         tap(13);
@@ -183,7 +177,7 @@
     }
 
     public void testSingleSelectMode_ShiftTap() {
-        mManager = new MultiSelectManager(mAdapter, mEventHelper, MultiSelectManager.MODE_SINGLE);
+        mManager = new MultiSelectManager(mAdapter, MultiSelectManager.MODE_SINGLE);
         mManager.addCallback(mCallback);
         longPress(13);
         shiftTap(20);
@@ -269,26 +263,13 @@
         assertEquals(selection.toString(), expected, selection.size());
     }
 
-    private static final class EventHelper implements MultiSelectManager.ItemFinder {
-
-        @Override
-        public int findItemPosition(MotionEvent e) {
-            throw new UnsupportedOperationException();
-        }
-    }
-
     private static final class TestCallback implements MultiSelectManager.Callback {
 
         Set<Integer> ignored = new HashSet<>();
-        private int mLastChangedPosition;
-        private boolean mLastChangedSelected;
         private boolean mSelectionChanged = false;
 
         @Override
-        public void onItemStateChanged(int position, boolean selected) {
-            this.mLastChangedPosition = position;
-            this.mLastChangedSelected = selected;
-        }
+        public void onItemStateChanged(int position, boolean selected) {}
 
         @Override
         public boolean onBeforeItemStateChange(int position, boolean selected) {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java
index aa50b48..f6683fa 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManager_GridModelTest.java
@@ -24,6 +24,7 @@
 import android.support.v7.widget.RecyclerView.OnScrollListener;
 import android.test.AndroidTestCase;
 import android.util.SparseBooleanArray;
+import android.view.View;
 
 import com.android.documentsui.MultiSelectManager.GridModel;
 
@@ -34,14 +35,14 @@
     private static final int VIEWPORT_HEIGHT = 500;
 
     private static GridModel model;
-    private static TestHelper helper;
+    private static TestEnvironment env;
     private static SparseBooleanArray lastSelection;
     private static int viewWidth;
 
     private static void setUp(int numChildren, int numColumns) {
-        helper = new TestHelper(numChildren, numColumns);
+        env = new TestEnvironment(numChildren, numColumns);
         viewWidth = VIEW_PADDING_PX + numColumns * (VIEW_PADDING_PX + CHILD_VIEW_EDGE_PX);
-        model = new GridModel(helper);
+        model = new GridModel(env);
         model.addOnSelectionChangedListener(
                 new GridModel.OnSelectionChangedListener() {
                     @Override
@@ -54,7 +55,7 @@
     @Override
     public void tearDown() {
         model = null;
-        helper = null;
+        env = null;
         lastSelection = null;
     }
 
@@ -176,12 +177,12 @@
     }
 
     private static void scroll(int dy) {
-        assertTrue(helper.verticalOffset + VIEWPORT_HEIGHT + dy <= helper.getTotalHeight());
-        helper.verticalOffset += dy;
+        assertTrue(env.verticalOffset + VIEWPORT_HEIGHT + dy <= env.getTotalHeight());
+        env.verticalOffset += dy;
         model.onScrolled(null, 0, dy);
     }
 
-    private static final class TestHelper implements MultiSelectManager.BandEnvironment {
+    private static final class TestEnvironment implements MultiSelectManager.SelectionEnvironment {
 
         public int horizontalOffset = 0;
         public int verticalOffset = 0;
@@ -189,7 +190,7 @@
         private final int mNumRows;
         private final int mNumChildren;
 
-        public TestHelper(int numChildren, int numColumns) {
+        public TestEnvironment(int numChildren, int numColumns) {
             mNumChildren = numChildren;
             mNumColumns = numColumns;
             mNumRows = (int) Math.ceil((double) numChildren / mNumColumns);
@@ -307,5 +308,15 @@
         public void removeCallback(Runnable r) {
             throw new UnsupportedOperationException();
         }
+
+        @Override
+        public int getAdapterPositionForChildView(View view) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void focusItem(int i) {
+            throw new UnsupportedOperationException();
+        }
     }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 9a91ca4..29b319f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -133,10 +133,6 @@
         mLockPatternView.setSaveEnabled(false);
         mLockPatternView.setOnPatternListener(new UnlockPatternListener());
 
-        // stealth mode will be the same for the life of this screen
-        mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
-                KeyguardUpdateMonitor.getCurrentUser()));
-
         // vibrate mode will be the same for the life of this screen
         mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
 
@@ -176,6 +172,8 @@
     @Override
     public void reset() {
         // reset lock pattern
+        mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
+                KeyguardUpdateMonitor.getCurrentUser()));
         mLockPatternView.enableInput();
         mLockPatternView.setEnabled(true);
         mLockPatternView.clearPattern();
diff --git a/packages/MtpDocumentsProvider/res/values/strings.xml b/packages/MtpDocumentsProvider/res/values/strings.xml
index 37efdb5..7a4087b 100644
--- a/packages/MtpDocumentsProvider/res/values/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values/strings.xml
@@ -14,7 +14,11 @@
      limitations under the License.
 -->
 
-<resources>
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Title of the external storage application [CHAR LIMIT=32] -->
     <string name="app_label">MTP Storage</string>
+    <!-- Name of MTP root shown in UI. Please align the two strings (device
+         model and storage name) in proper order in the language.
+         [CHAR LIMIT=32] -->
+    <string name="root_name"><xliff:g id="device_model" example="Nexus 9">%1$s</xliff:g> <xliff:g id="storage_name" example="Internal Storage">%2$s</xliff:g></string>
 </resources>
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
index b5694b7..cc510a9 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
@@ -16,25 +16,24 @@
 
 package com.android.mtp;
 
+import android.content.res.Resources;
 import android.database.MatrixCursor;
 import android.mtp.MtpConstants;
 import android.mtp.MtpObjectInfo;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 
-import java.util.Date;
-
 final class CursorHelper {
     static final int DUMMY_HANDLE_FOR_ROOT = 0;
 
     private CursorHelper() {
     }
 
-    static void addToCursor(MtpRoot root, MatrixCursor.RowBuilder builder) {
+    static void addToCursor(Resources resources, MtpRoot root, MatrixCursor.RowBuilder builder) {
         final Identifier identifier = new Identifier(
                 root.mDeviceId, root.mStorageId, DUMMY_HANDLE_FOR_ROOT);
         builder.add(Document.COLUMN_DOCUMENT_ID, identifier.toDocumentId());
-        builder.add(Document.COLUMN_DISPLAY_NAME, root.mDescription);
+        builder.add(Document.COLUMN_DISPLAY_NAME, root.getRootName(resources));
         builder.add(Document.COLUMN_MIME_TYPE, DocumentsContract.Document.MIME_TYPE_DIR);
         builder.add(Document.COLUMN_LAST_MODIFIED, null);
         builder.add(Document.COLUMN_FLAGS, 0);
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index a1a43c1..9d5850b 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -18,6 +18,7 @@
 
 import android.content.ContentResolver;
 import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.graphics.Point;
@@ -59,8 +60,8 @@
     private MtpManager mMtpManager;
     private ContentResolver mResolver;
     private Map<Integer, DeviceToolkit> mDeviceToolkits;
-    private DocumentLoader mDocumentLoaders;
     private RootScanner mRootScanner;
+    private Resources mResources;
 
     /**
      * Provides singleton instance to MtpDocumentsService.
@@ -72,6 +73,7 @@
     @Override
     public boolean onCreate() {
         sSingleton = this;
+        mResources = getContext().getResources();
         mMtpManager = new MtpManager(getContext());
         mResolver = getContext().getContentResolver();
         mDeviceToolkits = new HashMap<Integer, DeviceToolkit>();
@@ -80,7 +82,8 @@
     }
 
     @VisibleForTesting
-    void onCreateForTesting(MtpManager mtpManager, ContentResolver resolver) {
+    void onCreateForTesting(Resources resources, MtpManager mtpManager, ContentResolver resolver) {
+        mResources = resources;
         mMtpManager = mtpManager;
         mResolver = resolver;
         mDeviceToolkits = new HashMap<Integer, DeviceToolkit>();
@@ -99,10 +102,8 @@
             final MatrixCursor.RowBuilder builder = cursor.newRow();
             builder.add(Root.COLUMN_ROOT_ID, rootIdentifier.toRootId());
             builder.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
-            builder.add(Root.COLUMN_TITLE, root.mDescription);
-            builder.add(
-                    Root.COLUMN_DOCUMENT_ID,
-                    rootIdentifier.toDocumentId());
+            builder.add(Root.COLUMN_TITLE, root.getRootName(mResources));
+            builder.add(Root.COLUMN_DOCUMENT_ID, rootIdentifier.toDocumentId());
             builder.add(Root.COLUMN_AVAILABLE_BYTES , root.mFreeSpace);
         }
         cursor.setNotificationUri(
@@ -143,7 +144,7 @@
                 if (identifier.mStorageId != root.mStorageId)
                     continue;
                 final MatrixCursor cursor = new MatrixCursor(projection);
-                CursorHelper.addToCursor(root, cursor.newRow());
+                CursorHelper.addToCursor(mResources, root, cursor.newRow());
                 return cursor;
             }
         }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index af7f691..714936d 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -107,7 +107,10 @@
             }
             final MtpRoot[] results = new MtpRoot[storageIds.length];
             for (int i = 0; i < storageIds.length; i++) {
-                results[i] = new MtpRoot(deviceId, device.getStorageInfo(storageIds[i]));
+                results[i] = new MtpRoot(
+                        device.getDeviceId(),
+                        device.getDeviceInfo().getModel(),
+                        device.getStorageInfo(storageIds[i]));
             }
             return results;
         }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java
index 9dd53c0..ec338c3 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpRoot.java
@@ -16,6 +16,7 @@
 
 package com.android.mtp;
 
+import android.content.res.Resources;
 import android.mtp.MtpStorageInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -23,6 +24,7 @@
 class MtpRoot {
     final int mDeviceId;
     final int mStorageId;
+    final String mDeviceModelName;
     final String mDescription;
     final long mFreeSpace;
     final long mMaxCapacity;
@@ -31,21 +33,24 @@
     @VisibleForTesting
     MtpRoot(int deviceId,
             int storageId,
+            String deviceName,
             String description,
             long freeSpace,
             long maxCapacity,
             String volumeIdentifier) {
         mDeviceId = deviceId;
         mStorageId = storageId;
+        mDeviceModelName = deviceName;
         mDescription = description;
         mFreeSpace = freeSpace;
         mMaxCapacity = maxCapacity;
         mVolumeIdentifier = volumeIdentifier;
     }
 
-    MtpRoot(int deviceId, MtpStorageInfo storageInfo) {
+    MtpRoot(int deviceId, String deviceModelName, MtpStorageInfo storageInfo) {
         mDeviceId = deviceId;
         mStorageId = storageInfo.getStorageId();
+        mDeviceModelName = deviceModelName;
         mDescription = storageInfo.getDescription();
         mFreeSpace = storageInfo.getFreeSpace();
         mMaxCapacity = storageInfo.getMaxCapacity();
@@ -59,6 +64,7 @@
         final MtpRoot other = (MtpRoot) object;
         return mDeviceId == other.mDeviceId &&
                 mStorageId == other.mStorageId &&
+                mDeviceModelName.equals(other.mDeviceModelName) &&
                 mDescription.equals(other.mDescription) &&
                 mFreeSpace == other.mFreeSpace &&
                 mMaxCapacity == other.mMaxCapacity &&
@@ -67,7 +73,19 @@
 
     @Override
     public int hashCode() {
-        return mDeviceId ^ mStorageId ^ mDescription.hashCode() ^ ((int) mFreeSpace) ^
-                ((int) mMaxCapacity) ^ mVolumeIdentifier.hashCode();
+        return mDeviceId ^ mStorageId ^ mDeviceModelName.hashCode() ^ mDescription.hashCode() ^
+                ((int) mFreeSpace) ^ ((int) mMaxCapacity) ^ mVolumeIdentifier.hashCode();
+    }
+    
+    @Override
+    public String toString() {
+        return "MtpRoot{Name: " + mDeviceModelName + " " + mDescription + "}";
+    }
+    
+    String getRootName(Resources resources) {
+        return String.format(
+                resources.getString(R.string.root_name),
+                mDeviceModelName,
+                mDescription);
     }
 }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index 4b3a5cd..0c03814c 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -16,19 +16,21 @@
 
 package com.android.mtp;
 
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
 import android.database.Cursor;
 import android.mtp.MtpConstants;
-import android.mtp.MtpObjectInfo.Builder;
 import android.mtp.MtpObjectInfo;
 import android.net.Uri;
 import android.provider.DocumentsContract.Root;
 import android.provider.DocumentsContract;
 import android.test.AndroidTestCase;
+import android.test.mock.MockResources;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.util.Date;
 
 @SmallTest
 public class MtpDocumentsProviderTest extends AndroidTestCase {
@@ -37,13 +39,23 @@
     private TestContentResolver mResolver;
     private MtpDocumentsProvider mProvider;
     private TestMtpManager mMtpManager;
+    private final MockResources mResources = new MockResources() {
+        @Override
+        public String getString(int id) throws NotFoundException {
+            switch (id) {
+                case R.string.root_name:
+                    return "%1$s %2$s";
+            }
+            throw new NotFoundException();
+        }
+    };
 
     @Override
     public void setUp() throws IOException {
         mResolver = new TestContentResolver();
         mMtpManager = new TestMtpManager(getContext());
         mProvider = new MtpDocumentsProvider();
-        mProvider.onCreateForTesting(mMtpManager, mResolver);
+        mProvider.onCreateForTesting(mResources, mMtpManager, mResolver);
     }
 
     public void testOpenAndCloseDevice() throws Exception {
@@ -52,6 +64,7 @@
                 new MtpRoot(
                         0 /* deviceId */,
                         1 /* storageId */,
+                        "Device A" /* device model name */,
                         "Storage A" /* volume description */,
                         1024 /* free space */,
                         2048 /* total space */,
@@ -86,6 +99,7 @@
                 new MtpRoot(
                         0 /* deviceId */,
                         1 /* storageId */,
+                        "Device A" /* device model name */,
                         "Storage A" /* volume description */,
                         1024 /* free space */,
                         2048 /* total space */,
@@ -101,6 +115,7 @@
                 new MtpRoot(
                         0 /* deviceId */,
                         1 /* storageId */,
+                        "Device A" /* device model name */,
                         "Storage A" /* volume description */,
                         1024 /* free space */,
                         2048 /* total space */,
@@ -121,6 +136,7 @@
                 new MtpRoot(
                         0 /* deviceId */,
                         1 /* storageId */,
+                        "Device A" /* device model name */,
                         "Storage A" /* volume description */,
                         1024 /* free space */,
                         2048 /* total space */,
@@ -130,6 +146,7 @@
                 new MtpRoot(
                         1 /* deviceId */,
                         1 /* storageId */,
+                        "Device B" /* device model name */,
                         "Storage B" /* volume description */,
                         2048 /* free space */,
                         4096 /* total space */,
@@ -146,7 +163,7 @@
             assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             // TODO: Add storage icon for MTP devices.
             assertTrue(cursor.isNull(2) /* icon */);
-            assertEquals("Storage A", cursor.getString(3));
+            assertEquals("Device A Storage A", cursor.getString(3));
             assertEquals("0_1_0", cursor.getString(4));
             assertEquals(1024, cursor.getInt(5));
         }
@@ -162,7 +179,7 @@
             assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             // TODO: Add storage icon for MTP devices.
             assertTrue(cursor.isNull(2) /* icon */);
-            assertEquals("Storage B", cursor.getString(3));
+            assertEquals("Device B Storage B", cursor.getString(3));
             assertEquals("1_1_0", cursor.getString(4));
             assertEquals(2048, cursor.getInt(5));
         }
@@ -183,6 +200,7 @@
                 new MtpRoot(
                         1 /* deviceId */,
                         1 /* storageId */,
+                        "Device B" /* device model name */,
                         "Storage B" /* volume description */,
                         2048 /* free space */,
                         4096 /* total space */,
@@ -200,7 +218,7 @@
             assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             // TODO: Add storage icon for MTP devices.
             assertTrue(cursor.isNull(2) /* icon */);
-            assertEquals("Storage B", cursor.getString(3));
+            assertEquals("Device B Storage B", cursor.getString(3));
             assertEquals("1_1_0", cursor.getString(4));
             assertEquals(2048, cursor.getInt(5));
         }
@@ -265,6 +283,7 @@
                 new MtpRoot(
                         0 /* deviceId */,
                         1 /* storageId */,
+                        "Device A" /* device model name */,
                         "Storage A" /* volume description */,
                         1024 /* free space */,
                         4096 /* total space */,
@@ -276,7 +295,7 @@
         cursor.moveToNext();
         assertEquals("0_1_0", cursor.getString(0));
         assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
-        assertEquals("Storage A", cursor.getString(2));
+        assertEquals("Device A Storage A", cursor.getString(2));
         assertTrue(cursor.isNull(3));
         assertEquals(0, cursor.getInt(4));
         assertEquals(3072, cursor.getInt(5));
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
index 5605388..3d92cc2 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
@@ -18,12 +18,10 @@
 
 import android.content.Context;
 import android.mtp.MtpObjectInfo;
-import android.mtp.MtpObjectInfo.Builder;
 import android.os.ParcelFileDescriptor;
 
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index c8871c4..3efd33d 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -384,7 +384,7 @@
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"دستگاه قفل باقی می‌ماند تا زمانی که قفل آن را به صورت دستی باز کنید"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"دریافت سریع‌تر اعلان‌ها"</string>
     <string name="hidden_notifications_text" msgid="2326409389088668981">"قبل از باز کردن قفل آنها را مشاهده کنید"</string>
-    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"خیر، سپاسگزارم"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"نه سپاسگزارم"</string>
     <string name="hidden_notifications_setup" msgid="41079514801976810">"راه‌اندازی"</string>
     <string name="notification_expand_button_text" msgid="1037425494153780718">"مشاهده همه"</string>
     <string name="notification_collapse_button_text" msgid="6883253262134328057">"پنهان کردن همه"</string>
@@ -396,7 +396,7 @@
     <string name="screen_pinning_description" msgid="1346522416878235405">"تا زمانی که پین را بردارید، در نما نگه‌داشته می‌شود. برای برداشتن پین، برگشت و نمای کلی را به صورت هم‌زمان لمس کنید و نگه‌دارید."</string>
     <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"تا زمانی که پین را بردارید، در نما نگه‌داشته می‌شود. برای برداشتن پین، نمای کلی را لمس کنید و نگه‌دارید."</string>
     <string name="screen_pinning_positive" msgid="3783985798366751226">"متوجه شدم"</string>
-    <string name="screen_pinning_negative" msgid="3741602308343880268">"خیر متشکرم"</string>
+    <string name="screen_pinning_negative" msgid="3741602308343880268">"نه سپاسگزارم"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> مخفی شود؟"</string>
     <string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"دفعه بعد که آن را روشن کنید، در تنظیمات نشان داده می‌شود."</string>
     <string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"پنهان کردن"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 3593b34..6427644 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -313,7 +313,7 @@
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre brådskande aviseringar nedan"</string>
     <string name="notification_tap_again" msgid="8524949573675922138">"Tryck igen för att öppna"</string>
-    <string name="keyguard_unlock" msgid="8043466894212841998">"Dra uppåt om du vill låsa upp"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Svep uppåt om du vill låsa upp"</string>
     <string name="phone_hint" msgid="4872890986869209950">"Dra från ikonen och öppna telefonen"</string>
     <string name="voice_hint" msgid="8939888732119726665">"Dra från ikonen och öppna röstassistenten"</string>
     <string name="camera_hint" msgid="7939688436797157483">"Dra från ikonen och öppna kameran"</string>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index c070a0e..955efb5 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -20,6 +20,7 @@
         <attr name="keyCode" format="integer" />
         <!-- does this button generate longpress / repeat events? -->
         <attr name="keyRepeat" format="boolean" />
+        <attr name="android:contentDescription" />
     </declare-styleable>
     <declare-styleable name="ToggleSlider">
         <attr name="text" format="string" />
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
index a0ceb29..e6c42da 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
@@ -20,8 +20,8 @@
     public static float evaluate(float value) {
         float evaluation = 0.0f;
         if (value < 1.00) evaluation++;
-        if (value < 0.95) evaluation++;
         if (value < 0.90) evaluation++;
+        if (value < 0.70) evaluation++;
         return evaluation;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
index c125e00..652d969 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
@@ -27,10 +27,12 @@
 
     @Override
     public float getFalseTouchEvaluation(int type, Stroke stroke) {
+        float ratio;
         if (stroke.getTotalLength() == 0.0f) {
-            return 1.0f;
+            ratio = 1.0f;
+        } else {
+            ratio = stroke.getEndPointLength() / stroke.getTotalLength();
         }
-        return EndPointRatioEvaluator.evaluate(
-                stroke.getEndPointLength() / stroke.getTotalLength());
+        return EndPointRatioEvaluator.evaluate(ratio);
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index a7a5694..27d4c0e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -48,7 +48,7 @@
     private final float mDpi;
 
     private HistoryEvaluator mHistoryEvaluator;
-    private boolean mEnableClassifier = true;
+    private boolean mEnableClassifier = false;
     private int mCurrentType = Classifier.GENERIC;
 
     protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java
index 2a45fa3..d50d406 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java
@@ -20,8 +20,8 @@
     public static float evaluate(float value) {
         float evaluation = 0.0f;
         if (value < 1.00) evaluation++;
-        if (value < 0.95) evaluation++;
         if (value < 0.90) evaluation++;
+        if (value < 0.70) evaluation++;
         return evaluation;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
index c0e4a2d..afd8d01 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
@@ -19,9 +19,10 @@
 public class SpeedEvaluator {
     public static float evaluate(float value) {
         float evaluation = 0.0f;
-        if (value < 4.0 || value > 35.0) evaluation += 1.0;
-        if (value < 2.2) evaluation += 1.0;
-        if (value > 50.0) evaluation += 1.0;
+        if (value < 4.0) evaluation++;
+        if (value < 2.2) evaluation++;
+        if (value > 35.0) evaluation++;
+        if (value > 50.0) evaluation++;
         return evaluation;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
index 349aa9e..4c6cea0 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
@@ -19,8 +19,10 @@
 public class SpeedRatioEvaluator {
     public static float evaluate(float value) {
         float evaluation = 0.0f;
-        if (value > 9.0) ++evaluation;
-        if (value > 18.0) ++evaluation;
+        if (value <= 1.0) evaluation++;
+        if (value <= 0.5) evaluation++;
+        if (value > 9.0) evaluation++;
+        if (value > 18.0) evaluation++;
         return evaluation;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java
index 8f9a7e1..48b1b6e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java
@@ -19,10 +19,10 @@
 public class SpeedVarianceEvaluator {
     public static float evaluate(float value) {
         float evaluation = 0.0f;
-        if (value > 0.06) evaluation += 1.0;
-        if (value > 0.15) evaluation += 1.0;
-        if (value > 0.3) evaluation += 1.0;
-        if (value > 0.6) evaluation += 1.0;
+        if (value > 0.06) evaluation++;
+        if (value > 0.15) evaluation++;
+        if (value > 0.3) evaluation++;
+        if (value > 0.6) evaluation++;
         return evaluation;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 687f6c1..7b0a44f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -149,10 +149,7 @@
     }
 
     private boolean isFalseTouch() {
-        if (mFalsingManager.isClassiferEnabled()) {
-            return mFalsingManager.isFalseTouch();
-        }
-        return !mDraggedFarEnough;
+        return mFalsingManager.isFalseTouch() || !mDraggedFarEnough;
     }
 
     private void captureStartingChild(float x, float y) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 210be9f..33f21ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -31,6 +31,7 @@
 import android.view.ViewStub;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.LinearInterpolator;
+import android.widget.Chronometer;
 import android.widget.ImageView;
 
 import com.android.systemui.R;
@@ -88,6 +89,7 @@
     private NotificationGuts mGuts;
     private StatusBarNotification mStatusBarNotification;
     private boolean mIsHeadsUp;
+    private boolean mLastChronometerRunning = true;
     private View mExpandButton;
     private View mExpandButtonDivider;
     private ViewStub mExpandButtonStub;
@@ -295,6 +297,7 @@
      */
     public void setPinned(boolean pinned) {
         mIsPinned = pinned;
+        setChronometerRunning(mLastChronometerRunning);
     }
 
     public boolean isPinned() {
@@ -320,6 +323,41 @@
         return mJustClicked;
     }
 
+    public void setChronometerRunning(boolean running) {
+        mLastChronometerRunning = running;
+        setChronometerRunning(running, mPrivateLayout);
+        setChronometerRunning(running, mPublicLayout);
+        if (mChildrenContainer != null) {
+            List<ExpandableNotificationRow> notificationChildren =
+                    mChildrenContainer.getNotificationChildren();
+            for (int i = 0; i < notificationChildren.size(); i++) {
+                ExpandableNotificationRow child = notificationChildren.get(i);
+                child.setChronometerRunning(running);
+            }
+        }
+    }
+
+    private void setChronometerRunning(boolean running, NotificationContentView layout) {
+        if (layout != null) {
+            running = running || isPinned();
+            View contractedChild = layout.getContractedChild();
+            View expandedChild = layout.getExpandedChild();
+            View headsUpChild = layout.getHeadsUpChild();
+            setChronometerRunningForChild(running, contractedChild);
+            setChronometerRunningForChild(running, expandedChild);
+            setChronometerRunningForChild(running, headsUpChild);
+        }
+    }
+
+    private void setChronometerRunningForChild(boolean running, View child) {
+        if (child != null) {
+            View chronometer = child.findViewById(com.android.internal.R.id.chronometer);
+            if (chronometer instanceof Chronometer) {
+                ((Chronometer) chronometer).setStarted(running);
+            }
+        }
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 76edafa..ebe7785 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -229,7 +229,7 @@
         }
 
         // On expanding, single mouse click expands the panel instead of dragging.
-        if (isFullyCollapsed() && event.getDevice().getSources() == InputDevice.SOURCE_MOUSE) {
+        if (isFullyCollapsed() && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
             if (event.getAction() == MotionEvent.ACTION_UP) {
                 expand(true);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 4f7756e..56f6036 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -170,7 +170,6 @@
      */
     public void showNotification(NotificationData.Entry headsUp) {
         if (DEBUG) Log.v(TAG, "showNotification");
-        MetricsLogger.count(mContext, "note_peek", 1);
         addHeadsUpEntry(headsUp);
         updateNotification(headsUp, true);
         headsUp.setInterruption();
@@ -247,6 +246,9 @@
             return;
         }
         mHasPinnedNotification = hasPinnedNotification;
+        if (mHasPinnedNotification) {
+            MetricsLogger.count(mContext, "note_peek", 1);
+        }
         updateTouchableRegionListener();
         for (OnHeadsUpChangedListener listener : mListeners) {
             listener.onHeadsUpPinnedModeChanged(hasPinnedNotification);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 4c99792..4d268ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -18,12 +18,14 @@
 
 import android.app.ActivityManager;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.hardware.input.InputManager;
 import android.media.AudioManager;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.view.HapticFeedbackConstants;
 import android.view.InputDevice;
 import android.view.KeyCharacterMap;
@@ -43,6 +45,7 @@
 
 public class KeyButtonView extends ImageView {
 
+    private int mContentDescriptionRes;
     private long mDownTime;
     private int mCode;
     private int mTouchSlop;
@@ -79,8 +82,14 @@
 
         mSupportsLongpress = a.getBoolean(R.styleable.KeyButtonView_keyRepeat, true);
 
+        TypedValue value = new TypedValue();
+        if (a.getValue(R.styleable.KeyButtonView_android_contentDescription, value)) {
+            mContentDescriptionRes = value.resourceId;
+        }
+
         a.recycle();
 
+
         setClickable(true);
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -88,6 +97,15 @@
     }
 
     @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        if (mContentDescriptionRes != 0) {
+            setContentDescription(mContext.getString(mContentDescriptionRes));
+        }
+    }
+
+    @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
         if (mCode != 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 5e5f810..d50f8ac5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1789,6 +1789,7 @@
         ((ExpandableView) child).setOnHeightChangedListener(this);
         generateAddAnimation(child, false /* fromMoreCard */);
         updateAnimationState(child);
+        updateChronometerForChild(child);
         if (canChildBeDismissed(child)) {
             // Make sure the dismissButton is visible and not in the animated state.
             // We need to do this to avoid a race where a clearable notification is added after the
@@ -2298,6 +2299,21 @@
         mStackScrollAlgorithm.setIsExpanded(isExpanded);
         if (changed) {
             updateNotificationAnimationStates();
+            updateChronometers();
+        }
+    }
+
+    private void updateChronometers() {
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            updateChronometerForChild(getChildAt(i));
+        }
+    }
+
+    private void updateChronometerForChild(View child) {
+        if (child instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            row.setChronometerRunning(mIsExpanded);
         }
     }
 
@@ -2320,6 +2336,7 @@
         }
         mStackScrollAlgorithm.onReset(view);
         updateAnimationState(view);
+        updateChronometerForChild(view);
     }
 
     private void updateScrollPositionOnExpandInBottom(ExpandableView view) {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 87b490d..496e4df 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -109,6 +109,9 @@
     private static final String ACTION_STEP_IDLE_STATE =
             "com.android.server.device_idle.STEP_IDLE_STATE";
 
+    private static final String ACTION_STEP_LIGHT_IDLE_STATE =
+            "com.android.server.device_idle.STEP_LIGHT_IDLE_STATE";
+
     private AlarmManager mAlarmManager;
     private IBatteryStats mBatteryStats;
     private PowerManagerInternal mLocalPowerManager;
@@ -118,16 +121,16 @@
     private Sensor mMotionSensor;
     private LocationManager mLocationManager;
     private LocationRequest mLocationRequest;
-    private PendingIntent mSensingAlarmIntent;
     private PendingIntent mAlarmIntent;
+    private PendingIntent mLightAlarmIntent;
     private Intent mIdleIntent;
+    private Intent mLightIdleIntent;
     private Display mCurDisplay;
     private AnyMotionDetector mAnyMotionDetector;
     private boolean mEnabled;
     private boolean mForceIdle;
     private boolean mScreenOn;
     private boolean mCharging;
-    private boolean mSensing;
     private boolean mNotMoving;
     private boolean mLocating;
     private boolean mLocated;
@@ -138,7 +141,7 @@
 
     /** Device is currently active. */
     private static final int STATE_ACTIVE = 0;
-    /** Device is inactve (screen off, no motion) and we are waiting to for idle. */
+    /** Device is inactive (screen off, no motion) and we are waiting to for idle. */
     private static final int STATE_INACTIVE = 1;
     /** Device is past the initial inactive period, and waiting for the next idle period. */
     private static final int STATE_IDLE_PENDING = 2;
@@ -163,12 +166,35 @@
         }
     }
 
+    /** Device is currently active. */
+    private static final int LIGHT_STATE_ACTIVE = 0;
+    /** Device is inactive (screen off) and we are waiting to for the first light idle. */
+    private static final int LIGHT_STATE_INACTIVE = 1;
+    /** Device is in the light idle state, trying to stay asleep as much as possible. */
+    private static final int LIGHT_STATE_IDLE = 2;
+    /** Device is in the light idle state, but temporarily out of idle to do regular maintenance. */
+    private static final int LIGHT_STATE_IDLE_MAINTENANCE = 3;
+    /** Device light idle state is overriden, now applying full doze state. */
+    private static final int LIGHT_STATE_OVERRIDE = 4;
+    private static String lightStateToString(int state) {
+        switch (state) {
+            case LIGHT_STATE_ACTIVE: return "ACTIVE";
+            case LIGHT_STATE_INACTIVE: return "INACTIVE";
+            case LIGHT_STATE_IDLE: return "IDLE";
+            case LIGHT_STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
+            case LIGHT_STATE_OVERRIDE: return "OVERRIDE";
+            default: return Integer.toString(state);
+        }
+    }
+
     private int mState;
+    private int mLightState;
 
     private long mInactiveTimeout;
     private long mNextAlarmTime;
     private long mNextIdlePendingDelay;
     private long mNextIdleDelay;
+    private long mNextLightAlarmTime;
 
     public final AtomicFile mConfigFile;
 
@@ -250,10 +276,14 @@
                 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                     Uri data = intent.getData();
                     String ssp;
-                    if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
+                    if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
                         removePowerSaveWhitelistAppInternal(ssp);
                     }
                 }
+            } else if (ACTION_STEP_LIGHT_IDLE_STATE.equals(intent.getAction())) {
+                synchronized (DeviceIdleController.this) {
+                    stepLightIdleStateLocked();
+                }
             } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {
                 synchronized (DeviceIdleController.this) {
                     stepIdleStateLocked();
@@ -305,7 +335,7 @@
         public void onAccuracyChanged(Sensor sensor, int accuracy) {}
 
         public boolean registerLocked() {
-            boolean success = false;
+            boolean success;
             if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
                 success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor);
             } else {
@@ -380,6 +410,8 @@
      */
     private final class Constants extends ContentObserver {
         // Key names stored in the settings value.
+        private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to";
+        private static final String KEY_LIGHT_IDLE_PENDING_TIMEOUT = "light_idle_pending_to";
         private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
         private static final String KEY_SENSING_TIMEOUT = "sensing_to";
         private static final String KEY_LOCATING_TIMEOUT = "locating_to";
@@ -401,6 +433,22 @@
                 "sms_temp_app_whitelist_duration";
 
         /**
+         * This is the time, after becoming inactive, that we will start going
+         * in to light-weight idle mode.
+         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+         * @see #KEY_LIGHT_IDLE_TIMEOUT
+         */
+        public long LIGHT_IDLE_TIMEOUT;
+
+        /**
+         * This is the initial time, after light idle idle, that we will will sit in the
+         * LIGHT_IDLE_MAINTENANCE period for the system to run normally before returning to idle.
+         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
+         * @see #KEY_LIGHT_IDLE_PENDING_TIMEOUT
+         */
+        public long LIGHT_IDLE_PENDING_TIMEOUT;
+
+        /**
          * This is the time, after becoming inactive, at which we start looking at the
          * motion sensor to determine if the device is being left alone.  We don't do this
          * immediately after going inactive just because we don't want to be continually running
@@ -455,7 +503,8 @@
 
         /**
          * This is the initial time, after being idle, that we will allow ourself to be back
-         * in the IDLE_PENDING state allowing the system to run normally until we return to idle.
+         * in the IDLE_MAINTENANCE state allowing the system to run normally until we return to
+         * idle.
          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
          * @see #KEY_IDLE_PENDING_TIMEOUT
          */
@@ -555,6 +604,10 @@
                     Slog.e(TAG, "Bad device idle settings", e);
                 }
 
+                LIGHT_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_IDLE_TIMEOUT,
+                        !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L);
+                LIGHT_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_LIGHT_IDLE_PENDING_TIMEOUT,
+                        !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L);
                 INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
                         !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
                 SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
@@ -592,6 +645,14 @@
         void dump(PrintWriter pw) {
             pw.println("  Settings:");
 
+            pw.print("    "); pw.print(KEY_LIGHT_IDLE_TIMEOUT); pw.print("=");
+            TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw);
+            pw.println();
+
+            pw.print("    "); pw.print(KEY_LIGHT_IDLE_PENDING_TIMEOUT); pw.print("=");
+            TimeUtils.formatDuration(LIGHT_IDLE_PENDING_TIMEOUT, pw);
+            pw.println();
+
             pw.print("    "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
             TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
             pw.println();
@@ -689,9 +750,10 @@
 
     static final int MSG_WRITE_CONFIG = 1;
     static final int MSG_REPORT_IDLE_ON = 2;
-    static final int MSG_REPORT_IDLE_OFF = 3;
-    static final int MSG_REPORT_ACTIVE = 4;
-    static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 5;
+    static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
+    static final int MSG_REPORT_IDLE_OFF = 4;
+    static final int MSG_REPORT_ACTIVE = 5;
+    static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
 
     final class MyHandler extends Handler {
         MyHandler(Looper looper) {
@@ -704,43 +766,70 @@
                 case MSG_WRITE_CONFIG: {
                     handleWriteConfigFile();
                 } break;
-                case MSG_REPORT_IDLE_ON: {
+                case MSG_REPORT_IDLE_ON:
+                case MSG_REPORT_IDLE_ON_LIGHT: {
                     EventLogTags.writeDeviceIdleOnStart();
-                    mLocalPowerManager.setDeviceIdleMode(true);
+                    final boolean fullChanged;
+                    final boolean lightChanged;
+                    if (msg.what == MSG_REPORT_IDLE_ON) {
+                        fullChanged = mLocalPowerManager.setDeviceIdleMode(true);
+                        lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
+                    } else {
+                        fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
+                        lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true);
+                    }
                     try {
                         mNetworkPolicyManager.setDeviceIdleMode(true);
-                        mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());
+                        mBatteryStats.noteDeviceIdleMode(msg.what == MSG_REPORT_IDLE_ON
+                                ? BatteryStats.DEVICE_IDLE_MODE_FULL
+                                : BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid());
                     } catch (RemoteException e) {
                     }
-                    getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+                    if (fullChanged) {
+                        getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+                    }
+                    if (lightChanged) {
+                        getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
+                    }
                     EventLogTags.writeDeviceIdleOnComplete();
                 } break;
                 case MSG_REPORT_IDLE_OFF: {
                     EventLogTags.writeDeviceIdleOffStart("unknown");
-                    mLocalPowerManager.setDeviceIdleMode(false);
+                    final boolean fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
+                    final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
                     try {
                         mNetworkPolicyManager.setDeviceIdleMode(false);
-                        mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid());
+                        mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
+                                null, Process.myUid());
                     } catch (RemoteException e) {
                     }
-                    getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+                    if (fullChanged) {
+                        getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+                    }
+                    if (lightChanged) {
+                        getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
+                    }
                     EventLogTags.writeDeviceIdleOffComplete();
                 } break;
                 case MSG_REPORT_ACTIVE: {
                     String activeReason = (String)msg.obj;
                     int activeUid = msg.arg1;
-                    boolean needBroadcast = msg.arg2 != 0;
                     EventLogTags.writeDeviceIdleOffStart(
                             activeReason != null ? activeReason : "unknown");
-                    mLocalPowerManager.setDeviceIdleMode(false);
+                    final boolean fullChanged = mLocalPowerManager.setDeviceIdleMode(false);
+                    final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
                     try {
                         mNetworkPolicyManager.setDeviceIdleMode(false);
-                        mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);
+                        mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
+                                activeReason, activeUid);
                     } catch (RemoteException e) {
                     }
-                    if (needBroadcast) {
+                    if (fullChanged) {
                         getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
                     }
+                    if (lightChanged) {
+                        getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
+                    }
                     EventLogTags.writeDeviceIdleOffComplete();
                 } break;
                 case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
@@ -909,6 +998,7 @@
             // a battery update the next time the level drops.
             mCharging = true;
             mState = STATE_ACTIVE;
+            mLightState = LIGHT_STATE_ACTIVE;
             mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
         }
 
@@ -967,18 +1057,22 @@
                         .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                 mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
 
-                Intent intentSensing = new Intent(ACTION_STEP_IDLE_STATE)
+                Intent intentLight = new Intent(ACTION_STEP_LIGHT_IDLE_STATE)
                         .setPackage("android")
                         .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-                mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0);
+                mLightAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentLight, 0);
 
                 mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
                 mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                         | Intent.FLAG_RECEIVER_FOREGROUND);
+                mLightIdleIntent = new Intent(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
+                mLightIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+                        | Intent.FLAG_RECEIVER_FOREGROUND);
 
                 IntentFilter filter = new IntentFilter();
                 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
                 filter.addAction(ACTION_STEP_IDLE_STATE);
+                filter.addAction(ACTION_STEP_LIGHT_IDLE_STATE);
                 getContext().registerReceiver(mReceiver, filter);
                 filter = new IntentFilter();
                 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -1283,32 +1377,43 @@
     }
 
     void scheduleReportActiveLocked(String activeReason, int activeUid) {
-        Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
-                mState == STATE_IDLE ? 1 : 0, activeReason);
+        Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
         mHandler.sendMessage(msg);
     }
 
     void becomeActiveLocked(String activeReason, int activeUid) {
         if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
-        if (mState != STATE_ACTIVE) {
+        if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) {
             EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
+            EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
             scheduleReportActiveLocked(activeReason, activeUid);
             mState = STATE_ACTIVE;
+            mLightState = LIGHT_STATE_ACTIVE;
             mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
             resetIdleManagementLocked();
+            resetLightIdleManagementLocked();
         }
     }
 
     void becomeInactiveIfAppropriateLocked() {
         if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
-        if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled && mState == STATE_ACTIVE) {
+        if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled) {
             // Screen has turned off; we are now going to become inactive and start
             // waiting to see if we will ultimately go idle.
-            mState = STATE_INACTIVE;
-            if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
-            resetIdleManagementLocked();
-            scheduleAlarmLocked(mInactiveTimeout, false);
-            EventLogTags.writeDeviceIdle(mState, "no activity");
+            if (mState == STATE_ACTIVE) {
+                mState = STATE_INACTIVE;
+                if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
+                resetIdleManagementLocked();
+                scheduleAlarmLocked(mInactiveTimeout, false);
+                EventLogTags.writeDeviceIdle(mState, "no activity");
+            }
+            if (mLightState == LIGHT_STATE_ACTIVE) {
+                mLightState = LIGHT_STATE_INACTIVE;
+                if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
+                resetLightIdleManagementLocked();
+                scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_TIMEOUT);
+                EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
+            }
         }
     }
 
@@ -1316,12 +1421,15 @@
         mNextIdlePendingDelay = 0;
         mNextIdleDelay = 0;
         cancelAlarmLocked();
-        cancelSensingAlarmLocked();
         cancelLocatingLocked();
         stopMonitoringMotionLocked();
         mAnyMotionDetector.stop();
     }
 
+    void resetLightIdleManagementLocked() {
+        cancelLightAlarmLocked();
+    }
+
     void exitForceIdleLocked() {
         if (mForceIdle) {
             mForceIdle = false;
@@ -1331,6 +1439,37 @@
         }
     }
 
+    void stepLightIdleStateLocked() {
+        if (mLightState == LIGHT_STATE_OVERRIDE) {
+            // If we are already in full device idle mode, then
+            // there is nothing left to do for light mode.
+            return;
+        }
+
+        if (DEBUG) Slog.d(TAG, "stepLightIdleStateLocked: mLightState=" + mLightState);
+        EventLogTags.writeDeviceIdleLightStep();
+
+        switch (mLightState) {
+            case LIGHT_STATE_INACTIVE:
+            case LIGHT_STATE_IDLE_MAINTENANCE:
+                scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_TIMEOUT);
+                if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");
+                mLightState = LIGHT_STATE_IDLE;
+                EventLogTags.writeDeviceIdleLight(mLightState, "step");
+                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
+                break;
+            case LIGHT_STATE_IDLE:
+                // We have been idling long enough, now it is time to do some work.
+                scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_PENDING_TIMEOUT);
+                if (DEBUG) Slog.d(TAG,
+                        "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
+                mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
+                EventLogTags.writeDeviceIdleLight(mLightState, "step");
+                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
+                break;
+        }
+    }
+
     void stepIdleStateLocked() {
         if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
         EventLogTags.writeDeviceIdleStep();
@@ -1361,8 +1500,7 @@
                 mState = STATE_SENSING;
                 if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
                 EventLogTags.writeDeviceIdle(mState, "step");
-                scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT);
-                cancelSensingAlarmLocked();
+                cancelAlarmLocked();
                 cancelLocatingLocked();
                 mAnyMotionDetector.checkForAnyMotion();
                 mNotMoving = false;
@@ -1374,8 +1512,7 @@
                 mState = STATE_LOCATING;
                 if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
                 EventLogTags.writeDeviceIdle(mState, "step");
-                cancelSensingAlarmLocked();
-                scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT);
+                scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false);
                 if (mLocationManager != null
                         && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
                     mLocationManager.requestLocationUpdates(mLocationRequest,
@@ -1401,7 +1538,7 @@
 
                 // Otherwise, we have to move from locating into idle maintenance.
             case STATE_LOCATING:
-                cancelSensingAlarmLocked();
+                cancelAlarmLocked();
                 cancelLocatingLocked();
                 mAnyMotionDetector.stop();
             case STATE_IDLE_MAINTENANCE:
@@ -1412,6 +1549,10 @@
                 if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
                 mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
                 mState = STATE_IDLE;
+                if (mLightState != LIGHT_STATE_OVERRIDE) {
+                    mLightState = LIGHT_STATE_OVERRIDE;
+                    cancelLightAlarmLocked();
+                }
                 EventLogTags.writeDeviceIdle(mState, "step");
                 mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
                 break;
@@ -1439,11 +1580,22 @@
         // The device is not yet active, so we want to go back to the pending idle
         // state to wait again for no motion.  Note that we only monitor for motion
         // after moving out of the inactive state, so no need to worry about that.
+        boolean becomeInactive = false;
         if (mState != STATE_ACTIVE) {
             scheduleReportActiveLocked(type, Process.myUid());
             mState = STATE_ACTIVE;
             mInactiveTimeout = timeout;
             EventLogTags.writeDeviceIdle(mState, type);
+            becomeInactive = true;
+        }
+        if (mLightState == LIGHT_STATE_OVERRIDE) {
+            // We went out of light idle mode because we had started full idle mode...  let's
+            // now go back and reset things so we resume light idling if appropriate.
+            mLightState = STATE_ACTIVE;
+            EventLogTags.writeDeviceIdleLight(mLightState, type);
+            becomeInactive = true;
+        }
+        if (becomeInactive) {
             becomeInactiveIfAppropriateLocked();
         }
     }
@@ -1501,11 +1653,10 @@
         }
     }
 
-    void cancelSensingAlarmLocked() {
-        if (mSensing) {
-            if (DEBUG) Slog.d(TAG, "cancelSensingAlarmLocked()");
-            mAlarmManager.cancel(mSensingAlarmIntent);
-            mSensing = false;
+    void cancelLightAlarmLocked() {
+        if (mNextLightAlarmTime != 0) {
+            mNextLightAlarmTime = 0;
+            mAlarmManager.cancel(mLightAlarmIntent);
         }
     }
 
@@ -1536,13 +1687,18 @@
         }
     }
 
-    void scheduleSensingAlarmLocked(long delay) {
-        if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
-        cancelSensingAlarmLocked();
-        mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
+    void scheduleLightAlarmLocked(long delay) {
+        if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")");
+        if (mMotionSensor == null) {
+            // If there is no motion sensor on this device, then we won't schedule
+            // alarms, because we can't determine if the device is not moving.  This effectively
+            // turns off normal execution of device idling, although it is still possible to
+            // manually poke it by pretending like the alarm is going off.
+            return;
+        }
+        mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;
         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-            mNextAlarmTime, mSensingAlarmIntent);
-        mSensing = true;
+                mNextLightAlarmTime, mLightAlarmIntent);
     }
 
     private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
@@ -1778,7 +1934,21 @@
                 try {
                     exitForceIdleLocked();
                     stepIdleStateLocked();
-                    pw.print("Stepped to: "); pw.println(stateToString(mState));
+                    pw.print("Stepped to: ");
+                    pw.println(stateToString(mState));
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        } else if ("light-step".equals(cmd)) {
+            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+                    null);
+            synchronized (this) {
+                long token = Binder.clearCallingIdentity();
+                try {
+                    exitForceIdleLocked();
+                    stepLightIdleStateLocked();
+                    pw.print("Stepped to: "); pw.println(lightStateToString(mLightState));
                 } finally {
                     Binder.restoreCallingIdentity(token);
                 }
@@ -2041,8 +2211,7 @@
             pw.print("  mScreenOn="); pw.println(mScreenOn);
             pw.print("  mCharging="); pw.println(mCharging);
             pw.print("  mMotionActive="); pw.println(mMotionListener.active);
-            pw.print("  mSensing="); pw.print(mSensing); pw.print(" mNotMoving=");
-                    pw.println(mNotMoving);
+            pw.print("  mNotMoving="); pw.println(mNotMoving);
             pw.print("  mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
                     pw.print(mHasGps); pw.print(" mHasNetwork=");
                     pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
@@ -2052,7 +2221,9 @@
             if (mLastGpsLocation != null) {
                 pw.print("  mLastGpsLocation="); pw.println(mLastGpsLocation);
             }
-            pw.print("  mState="); pw.println(stateToString(mState));
+            pw.print("  mState="); pw.print(stateToString(mState));
+            pw.print(" mLightState=");
+            pw.println(lightStateToString(mLightState));
             pw.print("  mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
             pw.println();
             if (mNextAlarmTime != 0) {
@@ -2070,6 +2241,11 @@
                 TimeUtils.formatDuration(mNextIdleDelay, pw);
                 pw.println();
             }
+            if (mNextLightAlarmTime != 0) {
+                pw.print("  mNextLightAlarmTime=");
+                TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw);
+                pw.println();
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 9bf2aaa..516e2f4 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -194,6 +194,8 @@
 34006 device_idle_off_start (reason|3)
 34007 device_idle_off_phase (what|3)
 34008 device_idle_off_complete
+34009 device_idle_light (state|1|5), (reason|3)
+34010 device_idle_light_step
 
 # ---------------------------
 # DisplayManagerService.java
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index de48e71..7c0a820 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -25,6 +25,7 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.os.Environment;
+import android.os.SystemProperties;
 import android.os.UserManager;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -386,6 +387,12 @@
     }
 
     private int getUserParentOrSelfId(int userId) {
+        // Device supports File Based Encryption, and lock is applied per-user
+        if ("file".equals(SystemProperties.get("ro.crypto.type", "none"))) {
+            return userId;
+        }
+        // Device uses Block Based Encryption, and the parent user's lock is used for the whole
+        // device.
         if (userId != 0) {
             final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
             final UserInfo pi = um.getProfileParent(userId);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ee8a5e8..7df50d5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1229,7 +1229,6 @@
     int mSamplingInterval = 0;
     boolean mAutoStopProfiler = false;
     int mProfileType = 0;
-    String mOpenGlTraceApp = null;
     final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>();
     String mMemWatchDumpProcName;
     String mMemWatchDumpFile;
@@ -6161,11 +6160,6 @@
                 samplingInterval = mSamplingInterval;
                 profileAutoStop = mAutoStopProfiler;
             }
-            boolean enableOpenGlTrace = false;
-            if (mOpenGlTraceApp != null && mOpenGlTraceApp.equals(processName)) {
-                enableOpenGlTrace = true;
-                mOpenGlTraceApp = null;
-            }
             boolean enableTrackAllocation = false;
             if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
                 enableTrackAllocation = true;
@@ -6199,9 +6193,9 @@
             thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                     profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                     app.instrumentationUiAutomationConnection, testMode,
-                    mBinderTransactionTrackingEnabled, enableOpenGlTrace,
-                    enableTrackAllocation, isRestrictedBackupMode || !normalMode,
-                    app.persistent, new Configuration(mConfiguration), app.compat,
+                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
+                    isRestrictedBackupMode || !normalMode, app.persistent,
+                    new Configuration(mConfiguration), app.compat,
                     getCommonServicesLocked(app.isolated),
                     mCoreSettingsObserver.getCoreSettingsLocked());
             updateLruProcessLocked(app, false, null);
@@ -10809,19 +10803,6 @@
         }
     }
 
-    void setOpenGlTraceApp(ApplicationInfo app, String processName) {
-        synchronized (this) {
-            boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
-            if (!isDebuggable) {
-                if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
-                    throw new SecurityException("Process not debuggable: " + app.packageName);
-                }
-            }
-
-            mOpenGlTraceApp = processName;
-        }
-    }
-
     void setTrackAllocationApp(ApplicationInfo app, String processName) {
         synchronized (this) {
             boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
@@ -13936,15 +13917,6 @@
             pw.print("  mMemWatchDumpPid="); pw.print(mMemWatchDumpPid);
                     pw.print(" mMemWatchDumpUid="); pw.println(mMemWatchDumpUid);
         }
-        if (mOpenGlTraceApp != null) {
-            if (dumpPackage == null || dumpPackage.equals(mOpenGlTraceApp)) {
-                if (needSep) {
-                    pw.println();
-                    needSep = false;
-                }
-                pw.println("  mOpenGlTraceApp=" + mOpenGlTraceApp);
-            }
-        }
         if (mTrackAllocationApp != null) {
             if (dumpPackage == null || dumpPackage.equals(mTrackAllocationApp)) {
                 if (needSep) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 00664b4..a59f7ef 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -901,14 +901,8 @@
         prev.task.touchActiveTime();
         clearLaunchTime(prev);
         final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
-        // In freeform mode we only update the thumbnail when there is no thumbnail yet since every
-        // focus change will request a thumbnail to be taken.
-        // Note furthermore that since windows can change their content in freeform mode all the
-        // time a thumbnail is possibly constantly outdated.
-        if (mService.mHasRecents &&
-                (next == null || next.noDisplay || next.task != prev.task || uiSleeping) &&
-                (!prev.task.hasThumbnail() ||
-                        prev.task.stack.mStackId != FREEFORM_WORKSPACE_STACK_ID)) {
+        if (mService.mHasRecents
+                && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
             prev.updateThumbnailLocked(screenshotActivities(prev), null);
         }
         stopFullyDrawnTraceIfNeeded();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 2a36230..d6ad547 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -922,10 +922,6 @@
                     mService.setDebugApp(aInfo.processName, true, false);
                 }
 
-                if ((startFlags & ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
-                    mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
-                }
-
                 if ((startFlags & ActivityManager.START_FLAG_TRACK_ALLOCATION) != 0) {
                     mService.setTrackAllocationApp(aInfo.applicationInfo, aInfo.processName);
                 }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 62768c3..c7228ce 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -834,10 +834,10 @@
     }
 
     @Override
-    public void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid) {
+    public void noteDeviceIdleMode(int mode, String activeReason, int activeUid) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteDeviceIdleModeLocked(enabled, activeReason, activeUid);
+            mStats.noteDeviceIdleModeLocked(mode, activeReason, activeUid);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 5d5b5fe..1999f49 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -485,14 +485,6 @@
     }
 
     /**
-     * Returns true when we have a thumbnail.
-     * @return Returns true if there is a thumbnail.
-     */
-    boolean hasThumbnail() {
-        return mLastThumbnail != null;
-    }
-
-    /**
      * Sets the last thumbnail.
      * @return whether the thumbnail was set
      */
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index e6dc895..15e5393 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -104,6 +104,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Random;
 import java.util.Set;
 
@@ -258,7 +259,8 @@
 
     private BroadcastReceiver mDeviceIdleReceiver = new BroadcastReceiver() {
         @Override public void onReceive(Context context, Intent intent) {
-            boolean idle = mPowerManager.isDeviceIdleMode();
+            boolean idle = mPowerManager.isDeviceIdleMode()
+                    || mPowerManager.isLightDeviceIdleMode();
             mDeviceIsIdle = idle;
             if (idle) {
                 cancelActiveSync(
@@ -478,6 +480,7 @@
         context.registerReceiver(mStorageIntentReceiver, intentFilter);
 
         intentFilter = new IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+        intentFilter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
         context.registerReceiver(mDeviceIdleReceiver, intentFilter);
 
         intentFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
@@ -3370,7 +3373,7 @@
             if (!smaller.containsKey(key)) {
                 return false;
             }
-            if (!bigger.get(key).equals(smaller.get(key))) {
+            if (!Objects.equals(bigger.get(key), smaller.get(key))) {
                 return false;
             }
         }
@@ -3378,7 +3381,6 @@
     }
 
     /**
-     * TODO: Get rid of this when we separate sync settings extras from dev specified extras.
      * @return true if the provided key is used by the SyncManager in scheduling the sync.
      */
     private static boolean isSyncSetting(String key) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 3c50102..2b535b9 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -162,8 +162,12 @@
                     Slog.d(TAG, "Removing jobs for user: " + userId);
                 }
                 cancelJobsForUser(userId);
-            } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
-                updateIdleMode(mPowerManager != null ? mPowerManager.isDeviceIdleMode() : false);
+            } else if (PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())
+                    || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
+                updateIdleMode(mPowerManager != null
+                        ? (mPowerManager.isDeviceIdleMode()
+                                || mPowerManager.isLightDeviceIdleMode())
+                        : false);
             }
         }
     };
@@ -340,6 +344,7 @@
                     mBroadcastReceiver, UserHandle.ALL, filter, null, null);
             final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
             userFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+            userFilter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
             getContext().registerReceiverAsUser(
                     mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
             mPowerManager = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE);
diff --git a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
index db2b941..b06fe58 100644
--- a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
@@ -131,7 +131,7 @@
                 }
                 break;
             case MotionEvent.ACTION_HOVER_MOVE:
-                if (event.getDevice().getSources() == InputDevice.SOURCE_MOUSE) {
+                if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
                     if (!mMouseHoveringAtEdge && event.getY() == 0) {
                         mCallbacks.onMouseHoverAtTop();
                         mMouseHoveringAtEdge = true;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index ced0433..6498dd9 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -444,6 +444,9 @@
     // True if we are currently in device idle mode.
     private boolean mDeviceIdleMode;
 
+    // True if we are currently in light device idle mode.
+    private boolean mLightDeviceIdleMode;
+
     // Set of app ids that we will always respect the wake locks for.
     int[] mDeviceIdleWhitelist = new int[0];
 
@@ -2292,12 +2295,18 @@
         }
     }
 
-    private boolean isDeviceIdleModeInternal() {
+    boolean isDeviceIdleModeInternal() {
         synchronized (mLock) {
             return mDeviceIdleMode;
         }
     }
 
+    boolean isLightDeviceIdleModeInternal() {
+        synchronized (mLock) {
+            return mLightDeviceIdleMode;
+        }
+    }
+
     private void handleBatteryStateChangedLocked() {
         mDirty |= DIRTY_BATTERY_STATE;
         updatePowerStateLocked();
@@ -2368,7 +2377,7 @@
         }
     }
 
-    void setDeviceIdleModeInternal(boolean enabled) {
+    boolean setDeviceIdleModeInternal(boolean enabled) {
         synchronized (mLock) {
             if (mDeviceIdleMode != enabled) {
                 mDeviceIdleMode = enabled;
@@ -2378,7 +2387,19 @@
                 } else {
                     EventLogTags.writeDeviceIdleOffPhase("power");
                 }
+                return true;
             }
+            return false;
+        }
+    }
+
+    boolean setLightDeviceIdleModeInternal(boolean enabled) {
+        synchronized (mLock) {
+            if (mLightDeviceIdleMode != enabled) {
+                mLightDeviceIdleMode = enabled;
+                return true;
+            }
+            return false;
         }
     }
 
@@ -2671,6 +2692,7 @@
             pw.println("  mSandmanSummoned=" + mSandmanSummoned);
             pw.println("  mLowPowerModeEnabled=" + mLowPowerModeEnabled);
             pw.println("  mBatteryLevelLow=" + mBatteryLevelLow);
+            pw.println("  mLightDeviceIdleMode=" + mLightDeviceIdleMode);
             pw.println("  mDeviceIdleMode=" + mDeviceIdleMode);
             pw.println("  mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
             pw.println("  mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
@@ -3308,6 +3330,16 @@
             }
         }
 
+        @Override // Binder call
+        public boolean isLightDeviceIdleMode() {
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return isLightDeviceIdleModeInternal();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
         /**
          * Reboots the device.
          *
@@ -3576,8 +3608,13 @@
         }
 
         @Override
-        public void setDeviceIdleMode(boolean enabled) {
-            setDeviceIdleModeInternal(enabled);
+        public boolean setDeviceIdleMode(boolean enabled) {
+            return setDeviceIdleModeInternal(enabled);
+        }
+
+        @Override
+        public boolean setLightDeviceIdleMode(boolean enabled) {
+            return setLightDeviceIdleModeInternal(enabled);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 9f44fea..7abc048 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -16,6 +16,30 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManagerInternal.AppTransitionListener;
+import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindSourceAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindTargetAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
+
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -49,30 +73,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
-import static android.view.WindowManagerInternal.AppTransitionListener;
-import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindSourceAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindTargetAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
-
 // State management of app transitions.  When we are preparing for a
 // transition, mNextAppTransition will be the kind of transition to
 // perform or TRANSIT_NONE if we are not waiting.  If we are waiting,
@@ -543,14 +543,15 @@
 
             final int appWidth = appFrame.width();
             final int appHeight = appFrame.height();
+            // mTmpStartRect will contain an area around the launcher icon that was pressed. We will
+            // clip reveal from that area in the final area of the app.
             getDefaultNextAppTransitionStartRect(mTmpStartRect);
 
             float t = 0f;
             if (appHeight > 0) {
                 t = (float) mTmpStartRect.left / appHeight;
             }
-            int translationY = mClipRevealTranslationY
-                    + (int)(appHeight / 7f * t);
+            int translationY = mClipRevealTranslationY + (int)(appHeight / 7f * t);
 
             int centerX = mTmpStartRect.centerX();
             int centerY = mTmpStartRect.centerY();
@@ -562,15 +563,20 @@
                     centerX - halfWidth, centerX + halfWidth, 0, appWidth);
             clipAnimLR.setInterpolator(mClipHorizontalInterpolator);
             clipAnimLR.setDuration((long) (DEFAULT_APP_TRANSITION_DURATION / 2.5f));
+
             Animation clipAnimTB = new ClipRectTBAnimation(centerY - halfHeight - translationY,
                     centerY + halfHeight/ 2 - translationY, 0, appHeight);
             clipAnimTB.setInterpolator(mTouchResponseInterpolator);
             clipAnimTB.setDuration(DEFAULT_APP_TRANSITION_DURATION);
 
-            TranslateYAnimation translateY = new TranslateYAnimation(
-                    Animation.ABSOLUTE, translationY, Animation.ABSOLUTE, 0);
-            translateY.setInterpolator(mLinearOutSlowInInterpolator);
-            translateY.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+            // We might be animating entrance of a docked task, so we need the translate to account
+            // for the app frame in which the window will reside. Every other calculation here
+            // is performed as if the window started at 0,0.
+            translationY -= appFrame.top;
+            TranslateAnimation translate = new TranslateAnimation(-appFrame.left, 0, translationY,
+                    0);
+            translate.setInterpolator(mLinearOutSlowInInterpolator);
+            translate.setDuration(DEFAULT_APP_TRANSITION_DURATION);
 
             // Quick fade-in from icon to app window
             final int alphaDuration = DEFAULT_APP_TRANSITION_DURATION / 4;
@@ -581,7 +587,7 @@
             AnimationSet set = new AnimationSet(false);
             set.addAnimation(clipAnimLR);
             set.addAnimation(clipAnimTB);
-            set.addAnimation(translateY);
+            set.addAnimation(translate);
             set.addAnimation(alpha);
             set.setZAdjustment(Animation.ZORDER_TOP);
             set.initialize(appWidth, appHeight, appWidth, appHeight);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b409cea..6734fd6 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -16,10 +16,14 @@
 
 package com.android.server.wm;
 
-import static android.app.ActivityManager.*;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.ActivityManager.DOCKED_STACK_ID;
+import static android.app.ActivityManager.FIRST_STATIC_STACK_ID;
+import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.LAST_STATIC_STACK_ID;
 import static com.android.server.wm.WindowManagerService.DEBUG_TASK_MOVEMENT;
 import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
-import static com.android.server.wm.WindowManagerService.H.UNUSED;
 import static com.android.server.wm.WindowManagerService.TAG;
 
 import android.annotation.IntDef;
@@ -30,8 +34,8 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.DisplayInfo;
-
 import android.view.Surface;
+
 import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
@@ -424,12 +428,19 @@
             return;
         }
 
-        final TaskStack dockedStack = mDisplayContent.getDockedStackLocked();
+        final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
         if (dockedStack == null) {
             // Not sure why you are calling this method when there is no docked stack...
             throw new IllegalStateException(
                     "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
         }
+        if (!dockedStack.isVisibleLocked()) {
+            // The docked stack is being dismissed, but we caught before it finished being
+            // dismissed. In that case we want to treat it as if it is not occupying any space and
+            // let others occupy the whole display.
+            mDisplayContent.getLogicalDisplayRect(mTmpRect);
+            return;
+        }
 
         @DockSide
         final int dockedSide = dockedStack.getDockSide();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f571d9c..cd5fbb0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2886,6 +2886,8 @@
                     // isn't affected by the window insets.
                     contentInsets.set(win.mContentInsets);
                     appFrame.set(win.mFrame);
+                } else {
+                    appFrame.set(containingFrame);
                 }
             }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0860f02..4748c96 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3700,7 +3700,10 @@
             return;
         }
         enforceCrossUserPermission(userHandle);
-        enforceNotManagedProfile(userHandle, "set the active password");
+        // Managed Profile password can only be changed when file based encryption is present.
+        if (!"file".equals(SystemProperties.get("ro.crypto.type", "none"))) {
+            enforceNotManagedProfile(userHandle, "set the active password");
+        }
 
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java b/services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java
new file mode 100644
index 0000000..be6861c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java
@@ -0,0 +1,64 @@
+package com.android.server.content;
+
+import android.os.Bundle;
+
+import junit.framework.TestCase;
+
+public class SyncManagerTest extends TestCase {
+
+    final String KEY_1 = "key_1";
+    final String KEY_2 = "key_2";
+
+    public void testSyncExtrasEquals_WithNull() throws Exception {
+        Bundle b1 = new Bundle();
+        Bundle b2 = new Bundle();
+
+        b1.putString(KEY_1, null);
+        b2.putString(KEY_1, null);
+
+        assertTrue("Null extra not properly compared between bundles.",
+                SyncManager.syncExtrasEquals(b1, b2, false /* don't care about system extras */));
+    }
+
+    public void testSyncExtrasEqualsBigger_WithNull() throws Exception {
+        Bundle b1 = new Bundle();
+        Bundle b2 = new Bundle();
+
+        b1.putString(KEY_1, null);
+        b2.putString(KEY_1, null);
+
+        b1.putString(KEY_2, "bla");
+        b2.putString(KEY_2, "bla");
+
+        assertTrue("Extras not properly compared between bundles.",
+                SyncManager.syncExtrasEquals(b1, b2, false /* don't care about system extras */));
+    }
+
+    public void testSyncExtrasEqualsFails_differentValues() throws Exception {
+        Bundle b1 = new Bundle();
+        Bundle b2 = new Bundle();
+
+        b1.putString(KEY_1, null);
+        b2.putString(KEY_1, null);
+
+        b1.putString(KEY_2, "bla");
+        b2.putString(KEY_2, "ble");  // different key
+
+        assertFalse("Extras considered equal when they are different.",
+                SyncManager.syncExtrasEquals(b1, b2, false /* don't care about system extras */));
+    }
+
+    public void testSyncExtrasEqualsFails_differentNulls() throws Exception {
+        Bundle b1 = new Bundle();
+        Bundle b2 = new Bundle();
+
+        b1.putString(KEY_1, null);
+        b2.putString(KEY_1, "bla");  // different key
+
+        b1.putString(KEY_2, "ble");
+        b2.putString(KEY_2, "ble");
+
+        assertFalse("Extras considered equal when they are different.",
+                SyncManager.syncExtrasEquals(b1, b2, false /* don't care about system extras */));
+    }
+}
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index abb8803..703564c 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -122,6 +122,14 @@
     public static final int CAPABILITY_CALL_SUBJECT = 0x40;
 
     /**
+     * Flag indicating that this {@code PhoneAccount} should only be used for emergency calls.
+     * <p>
+     * See {@link #getCapabilities}
+     * @hide
+     */
+    public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 0x80;
+
+    /**
      * URI scheme for telephone number URIs.
      */
     public static final String SCHEME_TEL = "tel";
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index a410c53..e9b7819 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -152,6 +152,11 @@
     }
 
     @Override
+    public boolean isLightDeviceIdleMode() throws RemoteException {
+        return false;
+    }
+
+    @Override
     public boolean isScreenBrightnessBoosted() throws RemoteException {
         return false;
     }