Merge "Log window mode to tron."
diff --git a/api/current.txt b/api/current.txt
index d17f4b6..df6c473a3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -925,6 +925,7 @@
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
+    field public static final int pointerShape = 16844042; // 0x101050a
     field public static final int popupAnimationStyle = 16843465; // 0x10102c9
     field public static final int popupBackground = 16843126; // 0x1010176
     field public static final int popupCharacters = 16843332; // 0x1010244
@@ -40336,6 +40337,38 @@
     field public static final int ORIENTATION_UNKNOWN = -1; // 0xffffffff
   }
 
+  public final class PointerIcon implements android.os.Parcelable {
+    method public static android.view.PointerIcon createCustomIcon(android.graphics.Bitmap, float, float);
+    method public int describeContents();
+    method public static android.view.PointerIcon getSystemIcon(android.content.Context, int);
+    method public static android.view.PointerIcon loadCustomIcon(android.content.res.Resources, int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.PointerIcon> CREATOR;
+    field public static final int STYLE_ALIAS = 1010; // 0x3f2
+    field public static final int STYLE_ALL_SCROLL = 1013; // 0x3f5
+    field public static final int STYLE_ARROW = 1000; // 0x3e8
+    field public static final int STYLE_CELL = 1006; // 0x3ee
+    field public static final int STYLE_CONTEXT_MENU = 1001; // 0x3e9
+    field public static final int STYLE_COPY = 1011; // 0x3f3
+    field public static final int STYLE_CROSSHAIR = 1007; // 0x3ef
+    field public static final int STYLE_DEFAULT = 1000; // 0x3e8
+    field public static final int STYLE_GRAB = 1020; // 0x3fc
+    field public static final int STYLE_GRABBING = 1021; // 0x3fd
+    field public static final int STYLE_HAND = 1002; // 0x3ea
+    field public static final int STYLE_HELP = 1003; // 0x3eb
+    field public static final int STYLE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6
+    field public static final int STYLE_NO_DROP = 1012; // 0x3f4
+    field public static final int STYLE_NULL = 0; // 0x0
+    field public static final int STYLE_TEXT = 1008; // 0x3f0
+    field public static final int STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017; // 0x3f9
+    field public static final int STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016; // 0x3f8
+    field public static final int STYLE_VERTICAL_DOUBLE_ARROW = 1015; // 0x3f7
+    field public static final int STYLE_VERTICAL_TEXT = 1009; // 0x3f1
+    field public static final int STYLE_WAIT = 1004; // 0x3ec
+    field public static final int STYLE_ZOOM_IN = 1018; // 0x3fa
+    field public static final int STYLE_ZOOM_OUT = 1019; // 0x3fb
+  }
+
   public class ScaleGestureDetector {
     ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener);
     ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener, android.os.Handler);
@@ -40695,6 +40728,7 @@
     method public android.view.ViewParent getParentForAccessibility();
     method public float getPivotX();
     method public float getPivotY();
+    method public android.view.PointerIcon getPointerIcon(android.view.MotionEvent, float, float);
     method public android.content.res.Resources getResources();
     method public final int getRight();
     method protected float getRightFadingEdgeStrength();
@@ -40977,6 +41011,7 @@
     method public void setPaddingRelative(int, int, int, int);
     method public void setPivotX(float);
     method public void setPivotY(float);
+    method public void setPointerIcon(android.view.PointerIcon);
     method public void setPressed(boolean);
     method public final void setRight(int);
     method public void setRotation(float);
diff --git a/api/system-current.txt b/api/system-current.txt
index 492d6a9..ee975d1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1019,6 +1019,7 @@
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
+    field public static final int pointerShape = 16844042; // 0x101050a
     field public static final int popupAnimationStyle = 16843465; // 0x10102c9
     field public static final int popupBackground = 16843126; // 0x1010176
     field public static final int popupCharacters = 16843332; // 0x1010244
@@ -42674,6 +42675,38 @@
     field public static final int ORIENTATION_UNKNOWN = -1; // 0xffffffff
   }
 
+  public final class PointerIcon implements android.os.Parcelable {
+    method public static android.view.PointerIcon createCustomIcon(android.graphics.Bitmap, float, float);
+    method public int describeContents();
+    method public static android.view.PointerIcon getSystemIcon(android.content.Context, int);
+    method public static android.view.PointerIcon loadCustomIcon(android.content.res.Resources, int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.PointerIcon> CREATOR;
+    field public static final int STYLE_ALIAS = 1010; // 0x3f2
+    field public static final int STYLE_ALL_SCROLL = 1013; // 0x3f5
+    field public static final int STYLE_ARROW = 1000; // 0x3e8
+    field public static final int STYLE_CELL = 1006; // 0x3ee
+    field public static final int STYLE_CONTEXT_MENU = 1001; // 0x3e9
+    field public static final int STYLE_COPY = 1011; // 0x3f3
+    field public static final int STYLE_CROSSHAIR = 1007; // 0x3ef
+    field public static final int STYLE_DEFAULT = 1000; // 0x3e8
+    field public static final int STYLE_GRAB = 1020; // 0x3fc
+    field public static final int STYLE_GRABBING = 1021; // 0x3fd
+    field public static final int STYLE_HAND = 1002; // 0x3ea
+    field public static final int STYLE_HELP = 1003; // 0x3eb
+    field public static final int STYLE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6
+    field public static final int STYLE_NO_DROP = 1012; // 0x3f4
+    field public static final int STYLE_NULL = 0; // 0x0
+    field public static final int STYLE_TEXT = 1008; // 0x3f0
+    field public static final int STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017; // 0x3f9
+    field public static final int STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016; // 0x3f8
+    field public static final int STYLE_VERTICAL_DOUBLE_ARROW = 1015; // 0x3f7
+    field public static final int STYLE_VERTICAL_TEXT = 1009; // 0x3f1
+    field public static final int STYLE_WAIT = 1004; // 0x3ec
+    field public static final int STYLE_ZOOM_IN = 1018; // 0x3fa
+    field public static final int STYLE_ZOOM_OUT = 1019; // 0x3fb
+  }
+
   public class ScaleGestureDetector {
     ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener);
     ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener, android.os.Handler);
@@ -43033,6 +43066,7 @@
     method public android.view.ViewParent getParentForAccessibility();
     method public float getPivotX();
     method public float getPivotY();
+    method public android.view.PointerIcon getPointerIcon(android.view.MotionEvent, float, float);
     method public android.content.res.Resources getResources();
     method public final int getRight();
     method protected float getRightFadingEdgeStrength();
@@ -43315,6 +43349,7 @@
     method public void setPaddingRelative(int, int, int, int);
     method public void setPivotX(float);
     method public void setPivotY(float);
+    method public void setPointerIcon(android.view.PointerIcon);
     method public void setPressed(boolean);
     method public final void setRight(int);
     method public void setRotation(float);
diff --git a/api/test-current.txt b/api/test-current.txt
index 680f783..c494895 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -925,6 +925,7 @@
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
+    field public static final int pointerShape = 16844042; // 0x101050a
     field public static final int popupAnimationStyle = 16843465; // 0x10102c9
     field public static final int popupBackground = 16843126; // 0x1010176
     field public static final int popupCharacters = 16843332; // 0x1010244
@@ -40338,6 +40339,38 @@
     field public static final int ORIENTATION_UNKNOWN = -1; // 0xffffffff
   }
 
+  public final class PointerIcon implements android.os.Parcelable {
+    method public static android.view.PointerIcon createCustomIcon(android.graphics.Bitmap, float, float);
+    method public int describeContents();
+    method public static android.view.PointerIcon getSystemIcon(android.content.Context, int);
+    method public static android.view.PointerIcon loadCustomIcon(android.content.res.Resources, int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.PointerIcon> CREATOR;
+    field public static final int STYLE_ALIAS = 1010; // 0x3f2
+    field public static final int STYLE_ALL_SCROLL = 1013; // 0x3f5
+    field public static final int STYLE_ARROW = 1000; // 0x3e8
+    field public static final int STYLE_CELL = 1006; // 0x3ee
+    field public static final int STYLE_CONTEXT_MENU = 1001; // 0x3e9
+    field public static final int STYLE_COPY = 1011; // 0x3f3
+    field public static final int STYLE_CROSSHAIR = 1007; // 0x3ef
+    field public static final int STYLE_DEFAULT = 1000; // 0x3e8
+    field public static final int STYLE_GRAB = 1020; // 0x3fc
+    field public static final int STYLE_GRABBING = 1021; // 0x3fd
+    field public static final int STYLE_HAND = 1002; // 0x3ea
+    field public static final int STYLE_HELP = 1003; // 0x3eb
+    field public static final int STYLE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6
+    field public static final int STYLE_NO_DROP = 1012; // 0x3f4
+    field public static final int STYLE_NULL = 0; // 0x0
+    field public static final int STYLE_TEXT = 1008; // 0x3f0
+    field public static final int STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017; // 0x3f9
+    field public static final int STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016; // 0x3f8
+    field public static final int STYLE_VERTICAL_DOUBLE_ARROW = 1015; // 0x3f7
+    field public static final int STYLE_VERTICAL_TEXT = 1009; // 0x3f1
+    field public static final int STYLE_WAIT = 1004; // 0x3ec
+    field public static final int STYLE_ZOOM_IN = 1018; // 0x3fa
+    field public static final int STYLE_ZOOM_OUT = 1019; // 0x3fb
+  }
+
   public class ScaleGestureDetector {
     ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener);
     ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener, android.os.Handler);
@@ -40697,6 +40730,7 @@
     method public android.view.ViewParent getParentForAccessibility();
     method public float getPivotX();
     method public float getPivotY();
+    method public android.view.PointerIcon getPointerIcon(android.view.MotionEvent, float, float);
     method public android.content.res.Resources getResources();
     method public final int getRight();
     method protected float getRightFadingEdgeStrength();
@@ -40979,6 +41013,7 @@
     method public void setPaddingRelative(int, int, int, int);
     method public void setPivotX(float);
     method public void setPivotY(float);
+    method public void setPointerIcon(android.view.PointerIcon);
     method public void setPressed(boolean);
     method public final void setRight(int);
     method public void setRotation(float);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f3539ff..3962abd 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4399,10 +4399,14 @@
             // onConfigurationChanged
             int diff = activity.mCurrentConfig.diff(config);
             if (diff != 0) {
-                // If this activity doesn't handle any of the config changes
-                // then don't bother calling onConfigurationChanged as we're
-                // going to destroy it.
-                if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) {
+                // If this activity doesn't handle any of the config changes then don't bother
+                // calling onConfigurationChanged as we're going to destroy it.
+                // Except in the case where the configuration changed on the activity manager side,
+                // but wasn't big enough to cause a resource change so the activity wasn't destroyed.
+                // In this case we still want to change the configuration of the activity but not
+                // report it to the app.
+                if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
+                        || !reportToActivity) {
                     shouldChangeConfig = true;
                 }
             }
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 23e4d97..3910657 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -21,11 +21,14 @@
 import android.app.trust.ITrustManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.UserInfo;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.IBinder;
+import android.os.IUserManager;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.view.IWindowManager;
 import android.view.IOnKeyguardExitResult;
 import android.view.WindowManagerGlobal;
@@ -40,6 +43,7 @@
 public class KeyguardManager {
     private IWindowManager mWM;
     private ITrustManager mTrustManager;
+    private IUserManager mUserManager;
 
     /**
      * Intent used to prompt user for device credentials.
@@ -49,6 +53,13 @@
             "android.app.action.CONFIRM_DEVICE_CREDENTIAL";
 
     /**
+     * Intent used to prompt user for device credentials.
+     * @hide
+     */
+    public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER =
+            "android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER";
+
+    /**
      * A CharSequence dialog title to show to the user when used with a
      * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}.
      * @hide
@@ -71,7 +82,7 @@
      * @return the intent for launching the activity or null if no password is required.
      **/
     public Intent createConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) {
-        if (!isKeyguardSecure()) return null;
+        if (!isDeviceSecure()) return null;
         Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL);
         intent.putExtra(EXTRA_TITLE, title);
         intent.putExtra(EXTRA_DESCRIPTION, description);
@@ -81,6 +92,28 @@
     }
 
     /**
+     * Get an intent to prompt the user to confirm credentials (pin, pattern or password)
+     * for the given user. The caller is expected to launch this activity using
+     * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
+     * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge.
+     *
+     * @return the intent for launching the activity or null if no password is required.
+     *
+     * @hide
+     */
+    public Intent createConfirmDeviceCredentialIntent(
+            CharSequence title, CharSequence description, int userId) {
+        if (!isDeviceSecure(userId)) return null;
+        Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER);
+        intent.putExtra(EXTRA_TITLE, title);
+        intent.putExtra(EXTRA_DESCRIPTION, description);
+        intent.putExtra(Intent.EXTRA_USER_ID, userId);
+        // For security reasons, only allow this to come from system settings.
+        intent.setPackage("com.android.settings");
+        return intent;
+    }
+
+    /**
      * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
      * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
      * instead; this allows you to seamlessly hide the keyguard as your application
@@ -162,6 +195,8 @@
         mWM = WindowManagerGlobal.getWindowManagerService();
         mTrustManager = ITrustManager.Stub.asInterface(
                 ServiceManager.getService(Context.TRUST_SERVICE));
+        mUserManager = IUserManager.Stub.asInterface(
+                ServiceManager.getService(Context.USER_SERVICE));
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 3e8a51e..eb4cb91 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2165,7 +2165,7 @@
     @Deprecated
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
-        if (DBG) Log.d(TAG, "startLeScan(): " + serviceUuids);
+        if (DBG) Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
         if (callback == null) {
             if (DBG) Log.e(TAG, "startLeScan: null callback");
             return false;
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index fb81fd1..ae12c88 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -27,6 +27,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Arrays;
 import java.util.Locale;
 import java.util.UUID;
 import android.net.LocalSocket;
@@ -234,9 +235,9 @@
         BluetoothSocket as = new BluetoothSocket(this);
         as.mSocketState = SocketState.CONNECTED;
         FileDescriptor[] fds = mSocket.getAncillaryFileDescriptors();
-        if (DBG) Log.d(TAG, "socket fd passed by stack  fds: " + fds);
+        if (DBG) Log.d(TAG, "socket fd passed by stack fds: " + Arrays.toString(fds));
         if(fds == null || fds.length != 1) {
-            Log.e(TAG, "socket fd passed from stack failed, fds: " + fds);
+            Log.e(TAG, "socket fd passed from stack failed, fds: " + Arrays.toString(fds));
             as.close();
             throw new IOException("bt socket acept failed");
         }
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index ba9cf7c..1c3f45c 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -52,6 +52,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 /**
  * Content providers are one of the primary building blocks of Android applications, providing
@@ -1854,7 +1855,7 @@
             if (mAuthority != null) {
                 message += mAuthority;
             } else {
-                message += mAuthorities;
+                message += Arrays.toString(mAuthorities);
             }
             throw new SecurityException(message);
         }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 0633bff..b499af5 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -746,7 +746,7 @@
             pw.println(prefix + "splitPublicSourceDirs=" + Arrays.toString(splitPublicSourceDirs));
         }
         if (resourceDirs != null) {
-            pw.println(prefix + "resourceDirs=" + resourceDirs);
+            pw.println(prefix + "resourceDirs=" + Arrays.toString(resourceDirs));
         }
         if ((flags&DUMP_FLAG_DETAILS) != 0 && seinfo != null) {
             pw.println(prefix + "seinfo=" + seinfo);
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 3cda39a..a762f59 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -26,6 +26,7 @@
 import android.os.CancellationSignal;
 import android.os.OperationCanceledException;
 import android.os.ParcelFileDescriptor;
+import android.os.Trace;
 import android.util.Log;
 import android.util.LruCache;
 import android.util.Printer;
@@ -1330,6 +1331,10 @@
                     }
                 }
                 operation.mCookie = newOperationCookieLocked(index);
+                if (Trace.isTagEnabled(Trace.TRACE_TAG_DATABASE)) {
+                    Trace.asyncTraceBegin(Trace.TRACE_TAG_DATABASE, operation.getTraceMethodName(),
+                            operation.mCookie);
+                }
                 mIndex = index;
                 return operation.mCookie;
             }
@@ -1367,6 +1372,10 @@
         private boolean endOperationDeferLogLocked(int cookie) {
             final Operation operation = getOperationLocked(cookie);
             if (operation != null) {
+                if (Trace.isTagEnabled(Trace.TRACE_TAG_DATABASE)) {
+                    Trace.asyncTraceEnd(Trace.TRACE_TAG_DATABASE, operation.getTraceMethodName(),
+                            operation.mCookie);
+                }
                 operation.mEndTime = System.currentTimeMillis();
                 operation.mFinished = true;
                 return SQLiteDebug.DEBUG_LOG_SLOW_QUERIES && SQLiteDebug.shouldLogSlowQuery(
@@ -1439,6 +1448,12 @@
     }
 
     private static final class Operation {
+        // Trim all SQL statements to 256 characters inside the trace marker.
+        // This limit gives plenty of context while leaving space for other
+        // entries in the trace buffer (and ensures atrace doesn't truncate the
+        // marker for us, potentially losing metadata in the process).
+        private static final int MAX_TRACE_METHOD_NAME_LEN = 256;
+
         public long mStartTime;
         public long mEndTime;
         public String mKind;
@@ -1492,6 +1507,13 @@
             return mException != null ? "failed" : "succeeded";
         }
 
+        private String getTraceMethodName() {
+            String methodName = mKind + " " + mSql;
+            if (methodName.length() > MAX_TRACE_METHOD_NAME_LEN)
+                return methodName.substring(0, MAX_TRACE_METHOD_NAME_LEN);
+            return methodName;
+        }
+
         private String getFormattedStartTime() {
             // Note: SimpleDateFormat is not thread-safe, cannot be compile-time created, and is
             //       relatively expensive to create during preloading. This method is only used
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 174291e..ff33bd9 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -24,6 +24,7 @@
 import android.os.IBinder;
 import android.view.InputDevice;
 import android.view.InputEvent;
+import android.view.PointerIcon;
 
 /** @hide */
 interface IInputManager {
@@ -71,4 +72,5 @@
     void cancelVibrate(int deviceId, IBinder token);
 
     void setPointerIconShape(int shapeId);
+    void setCustomPointerIcon(in PointerIcon icon);
 }
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 201afee..fab4718 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,6 +16,7 @@
 
 package android.hardware.input;
 
+import android.view.PointerIcon;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.ArrayUtils;
 
@@ -819,6 +820,15 @@
         }
     }
 
+    /** @hide */
+    public void setCustomPointerIcon(PointerIcon icon) {
+        try {
+            mIm.setCustomPointerIcon(icon);
+        } catch (RemoteException ex) {
+            // Do nothing.
+        }
+    }
+
     private void populateInputDevicesLocked() {
         if (mInputDevicesChangedListener == null) {
             final InputDevicesChangedListener listener = new InputDevicesChangedListener();
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 7529c52..9e8103a 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -79,6 +79,8 @@
     public static final long TRACE_TAG_PACKAGE_MANAGER = 1L << 18;
     /** @hide */
     public static final long TRACE_TAG_SYSTEM_SERVER = 1L << 19;
+    /** @hide */
+    public static final long TRACE_TAG_DATABASE = 1L << 20;
 
     private static final long TRACE_TAG_NOT_READY = 1L << 63;
     private static final int MAX_SECTION_NAME_LEN = 127;
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 77a4485..084ff77 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -660,6 +660,16 @@
     }
 
     /**
+     * Builds URI for user home directory on external (local) storage.
+     * {@hide}
+     */
+    public static Uri buildHomeUri() {
+        // TODO: Avoid this type of interpackage copying. Added here to avoid
+        // direct coupling, but not ideal.
+        return DocumentsContract.buildRootUri("com.android.externalstorage.documents", "home");
+    }
+
+    /**
      * Build URI representing the recently modified documents of a specific root
      * in a document provider. When queried, a provider will return zero or more
      * rows with columns defined by {@link Document}.
diff --git a/core/java/android/security/net/config/ManifestConfigSource.java b/core/java/android/security/net/config/ManifestConfigSource.java
index bf1fb8a..0e137cd 100644
--- a/core/java/android/security/net/config/ManifestConfigSource.java
+++ b/core/java/android/security/net/config/ManifestConfigSource.java
@@ -79,7 +79,9 @@
                 if (DBG) {
                     Log.d(LOG_TAG, "No Network Security Config specified, using platform default");
                 }
-                source = new DefaultConfigSource();
+                boolean usesCleartextTraffic =
+                        (info.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0;
+                source = new DefaultConfigSource(usesCleartextTraffic);
             }
             mConfigSource = source;
             return mConfigSource;
@@ -87,9 +89,18 @@
     }
 
     private static final class DefaultConfigSource implements ConfigSource {
+
+        private final NetworkSecurityConfig mDefaultConfig;
+
+        public DefaultConfigSource(boolean usesCleartextTraffic) {
+            mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder()
+                    .setCleartextTrafficPermitted(usesCleartextTraffic)
+                    .build();
+       }
+
         @Override
         public NetworkSecurityConfig getDefaultConfig() {
-            return NetworkSecurityConfig.DEFAULT;
+            return mDefaultConfig;
         }
 
         @Override
diff --git a/core/java/android/security/net/config/RootTrustManager.java b/core/java/android/security/net/config/RootTrustManager.java
index e307ad0..b4e58e6 100644
--- a/core/java/android/security/net/config/RootTrustManager.java
+++ b/core/java/android/security/net/config/RootTrustManager.java
@@ -71,6 +71,10 @@
      */
     public List<X509Certificate> checkServerTrusted(X509Certificate[] certs, String authType,
             String hostname) throws CertificateException {
+        if (hostname == null && mConfig.hasPerDomainConfigs()) {
+            throw new CertificateException(
+                    "Domain specific configurations require that the hostname be provided");
+        }
         NetworkSecurityConfig config = mConfig.getConfigForHostname(hostname);
         return config.getTrustManager().checkServerTrusted(certs, authType, hostname);
     }
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index 5d9d929..568b267 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -72,10 +72,20 @@
                 return result;
             }
 
-            // TODO: Convert this a proper locale-fallback system
+            // If there's a variant, fall back to language+variant only, if available
+            final String variant = locale.getVariant();
+            if (!variant.isEmpty()) {
+                final Locale languageAndVariantOnlyLocale =
+                        new Locale(locale.getLanguage(), "", variant);
+                result = sMap.get(languageAndVariantOnlyLocale);
+                if (result != null) {
+                    sMap.put(locale, result);
+                    return result;
+                }
+            }
 
             // Fall back to language-only, if available
-            Locale languageOnlyLocale = new Locale(locale.getLanguage());
+            final Locale languageOnlyLocale = new Locale(locale.getLanguage());
             result = sMap.get(languageOnlyLocale);
             if (result != null) {
                 sMap.put(locale, result);
@@ -83,9 +93,9 @@
             }
 
             // Fall back to script-only, if available
-            String script = locale.getScript();
+            final String script = locale.getScript();
             if (!script.equals("")) {
-                Locale scriptOnlyLocale = new Locale.Builder()
+                final Locale scriptOnlyLocale = new Locale.Builder()
                         .setLanguage("und")
                         .setScript(script)
                         .build();
@@ -142,6 +152,11 @@
         {"en-UM", "en-US"}, // English (United States Minor Outlying Islands)
         {"en-VI", "en-US"}, // English (Virgin Islands)
 
+        // For German, we're assuming the 1996 (and later) orthography by default.
+        {"de", "de-1996"},
+        // Liechtenstein uses the Swiss hyphenation rules for the 1901 orthography.
+        {"de-LI-1901", "de-CH-1901"},
+
         // Norwegian is very probably Norwegian Bokmål.
         {"no", "nb"},
 
@@ -166,7 +181,18 @@
         sMap.put(null, null);
 
         // TODO: replace this with a discovery-based method that looks into /system/usr/hyphen-data
-        String[] availableLanguages = {"en-US", "es", "eu", "hu", "hy", "nb", "nn", "und-Ethi"};
+        String[] availableLanguages = {
+            "de-1901", "de-1996", "de-CH-1901",
+            "en-US",
+            "es",
+            "eu",
+            "hu",
+            "hy",
+            "nb",
+            "nn",
+            "pt",
+            "und-Ethi"
+        };
         for (int i = 0; i < availableLanguages.length; i++) {
             String languageTag = availableLanguages[i];
             Hyphenator h = loadHyphenator(languageTag);
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 46b9a46..88cd7ca 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -784,6 +784,15 @@
     }
 
     /**
+     * Specifies the current custom pointer.
+     * @param icon the icon data.
+     * @hide
+     */
+    public void setCustomPointerIcon(PointerIcon icon) {
+        InputManager.getInstance().setCustomPointerIcon(icon);
+    }
+
+    /**
      * Provides information about the range of values for a particular {@link MotionEvent} axis.
      *
      * @see InputDevice#getMotionRange(int)
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 55cf56f..f037958 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1779,6 +1779,7 @@
         switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_CENTER:
             case KeyEvent.KEYCODE_ENTER:
+            case KeyEvent.KEYCODE_SPACE:
                 return true;
             default:
                 return false;
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index d2a7d4a..aa879cd 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -16,8 +16,10 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.util.SparseArray;
 import com.android.internal.util.XmlUtils;
 
 import android.annotation.XmlRes;
@@ -39,13 +41,11 @@
  * Pointer icons can be provided either by the system using system styles,
  * or by applications using bitmaps or application resources.
  * </p>
- *
- * @hide
  */
 public final class PointerIcon implements Parcelable {
     private static final String TAG = "PointerIcon";
 
-    /** Style constant: Custom icon with a user-supplied bitmap. */
+    /** {@hide} Style constant: Custom icon with a user-supplied bitmap. */
     public static final int STYLE_CUSTOM = -1;
 
     /** Style constant: Null icon.  It has no bitmap. */
@@ -54,6 +54,7 @@
     /** Style constant: no icons are specified. If all views uses this, then falls back
      * to the default style, but this is helpful to distinguish a view explicitly want
      * to have the default icon.
+     * @hide
      */
     public static final int STYLE_NOT_SPECIFIED = 1;
 
@@ -135,10 +136,11 @@
     // conflicts with any system styles that may be defined in the future.
     private static final int STYLE_OEM_FIRST = 10000;
 
-    /** {@hide} The default pointer icon. */
+    /** The default pointer icon. */
     public static final int STYLE_DEFAULT = STYLE_ARROW;
 
     private static final PointerIcon gNullIcon = new PointerIcon(STYLE_NULL);
+    private static final SparseArray<PointerIcon> gSystemIcons = new SparseArray<PointerIcon>();
 
     private final int mStyle;
     private int mSystemIconResourceId;
@@ -160,6 +162,7 @@
      * @return The null pointer icon.
      *
      * @see #STYLE_NULL
+     * @hide
      */
     public static PointerIcon getNullIcon() {
         return gNullIcon;
@@ -172,8 +175,9 @@
      * @return The default pointer icon.
      *
      * @throws IllegalArgumentException if context is null.
+     * @hide
      */
-    public static PointerIcon getDefaultIcon(Context context) {
+    public static PointerIcon getDefaultIcon(@NonNull Context context) {
         return getSystemIcon(context, STYLE_DEFAULT);
     }
 
@@ -187,7 +191,7 @@
      *
      * @throws IllegalArgumentException if context is null.
      */
-    public static PointerIcon getSystemIcon(Context context, int style) {
+    public static PointerIcon getSystemIcon(@NonNull Context context, int style) {
         if (context == null) {
             throw new IllegalArgumentException("context must not be null");
         }
@@ -196,6 +200,11 @@
             return gNullIcon;
         }
 
+        PointerIcon icon = gSystemIcons.get(style);
+        if (icon != null) {
+            return icon;
+        }
+
         int styleIndex = getSystemIconStyleIndex(style);
         if (styleIndex == 0) {
             styleIndex = getSystemIconStyleIndex(STYLE_DEFAULT);
@@ -217,12 +226,13 @@
             return style == STYLE_DEFAULT ? gNullIcon : getSystemIcon(context, STYLE_DEFAULT);
         }
 
-        PointerIcon icon = new PointerIcon(style);
+        icon = new PointerIcon(style);
         if ((resourceId & 0xff000000) == 0x01000000) {
             icon.mSystemIconResourceId = resourceId;
         } else {
             icon.loadResource(context, context.getResources(), resourceId);
         }
+        gSystemIcons.append(style, icon);
         return icon;
     }
 
@@ -239,7 +249,8 @@
      * @throws IllegalArgumentException if bitmap is null, or if the x/y hotspot
      *         parameters are invalid.
      */
-    public static PointerIcon createCustomIcon(Bitmap bitmap, float hotSpotX, float hotSpotY) {
+    public static PointerIcon createCustomIcon(
+            @NonNull Bitmap bitmap, float hotSpotX, float hotSpotY) {
         if (bitmap == null) {
             throw new IllegalArgumentException("bitmap must not be null");
         }
@@ -273,7 +284,7 @@
      * @throws Resources.NotFoundException if the resource was not found or the drawable
      * linked in the resource was not found.
      */
-    public static PointerIcon loadCustomIcon(Resources resources, @XmlRes int resourceId) {
+    public static PointerIcon loadCustomIcon(@NonNull Resources resources, @XmlRes int resourceId) {
         if (resources == null) {
             throw new IllegalArgumentException("resources must not be null");
         }
@@ -291,10 +302,9 @@
      * @return The loaded pointer icon.
      *
      * @throws IllegalArgumentException if context is null.
-     * @see #isLoaded()
      * @hide
      */
-    public PointerIcon load(Context context) {
+    public PointerIcon load(@NonNull Context context) {
         if (context == null) {
             throw new IllegalArgumentException("context must not be null");
         }
@@ -309,83 +319,11 @@
         return result;
     }
 
-    /**
-     * Returns true if the pointer icon style is {@link #STYLE_NULL}.
-     *
-     * @return True if the pointer icon style is {@link #STYLE_NULL}.
-     */
-    public boolean isNullIcon() {
-        return mStyle == STYLE_NULL;
-    }
-
-    /**
-     * Returns true if the pointer icon has been loaded and its bitmap and hotspot
-     * information are available.
-     *
-     * @return True if the pointer icon is loaded.
-     * @see #load(Context)
-     */
-    public boolean isLoaded() {
-        return mBitmap != null || mStyle == STYLE_NULL;
-    }
-
-    /**
-     * Gets the style of the pointer icon.
-     *
-     * @return The pointer icon style.
-     */
+    /** @hide */
     public int getStyle() {
         return mStyle;
     }
 
-    /**
-     * Gets the bitmap of the pointer icon.
-     *
-     * @return The pointer icon bitmap, or null if the style is {@link #STYLE_NULL}.
-     *
-     * @throws IllegalStateException if the bitmap is not loaded.
-     * @see #isLoaded()
-     * @see #load(Context)
-     */
-    public Bitmap getBitmap() {
-        throwIfIconIsNotLoaded();
-        return mBitmap;
-    }
-
-    /**
-     * Gets the X offset of the pointer icon hotspot.
-     *
-     * @return The hotspot X offset.
-     *
-     * @throws IllegalStateException if the bitmap is not loaded.
-     * @see #isLoaded()
-     * @see #load(Context)
-     */
-    public float getHotSpotX() {
-        throwIfIconIsNotLoaded();
-        return mHotSpotX;
-    }
-
-    /**
-     * Gets the Y offset of the pointer icon hotspot.
-     *
-     * @return The hotspot Y offset.
-     *
-     * @throws IllegalStateException if the bitmap is not loaded.
-     * @see #isLoaded()
-     * @see #load(Context)
-     */
-    public float getHotSpotY() {
-        throwIfIconIsNotLoaded();
-        return mHotSpotY;
-    }
-
-    private void throwIfIconIsNotLoaded() {
-        if (!isLoaded()) {
-            throw new IllegalStateException("The icon is not loaded.");
-        }
-    }
-
     public static final Parcelable.Creator<PointerIcon> CREATOR
             = new Parcelable.Creator<PointerIcon>() {
         public PointerIcon createFromParcel(Parcel in) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 183ccf3..afa6c78 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2628,7 +2628,7 @@
     static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
 
     /**
-     * Value indicating {@link PointerIcon.STYLE_NOT_SPECIFIED}.
+     * Value indicating no specific pointer icons.
      */
     private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
 
@@ -2638,14 +2638,9 @@
     private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
 
     /**
-     * Value incicating {@link PointerIcon.STYLE_CUSTOM}.
-     */
-    private static final int PFLAG3_POINTER_ICON_CUSTOM = 2 << PFLAG3_POINTER_ICON_LSHIFT;
-
-    /**
      * The base value for other pointer icon shapes.
      */
-    private static final int PFLAG3_POINTER_ICON_VALUE_START = 3 << PFLAG3_POINTER_ICON_LSHIFT;
+    private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
 
     /**
      * Always allow a user to over-scroll this view, provided it is a
@@ -3927,6 +3922,11 @@
     private HandlerActionQueue mRunQueue;
 
     /**
+     * The pointer icon when the mouse hovers on this view. The default is null.
+     */
+    private PointerIcon mPointerIcon;
+
+    /**
      * @hide
      */
     String mStartActivityRequestWho;
@@ -4487,6 +4487,12 @@
                         initializeScrollIndicators = true;
                     }
                     break;
+                case R.styleable.View_pointerShape:
+                    final int pointerShape = a.getInt(attr, PointerIcon.STYLE_NOT_SPECIFIED);
+                    if (pointerShape != PointerIcon.STYLE_NOT_SPECIFIED) {
+                        setPointerIcon(PointerIcon.getSystemIcon(context, pointerShape));
+                    }
+                    break;
             }
         }
 
@@ -10156,8 +10162,8 @@
     /**
      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
-     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
-     * {@link KeyEvent#KEYCODE_ENTER} is released.
+     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
+     * or {@link KeyEvent#KEYCODE_SPACE} is released.
      * <p>Key presses in software keyboards will generally NOT trigger this listener,
      * although some may elect to do so in some situations. Do not rely on this to
      * catch software key presses.
@@ -21185,42 +21191,25 @@
         }
     }
 
-    /** @hide */
-    public int getPointerShape(MotionEvent event, float x, float y) {
-        final int value = (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK);
-        switch (value) {
-            case PFLAG3_POINTER_ICON_NOT_SPECIFIED:
-                return PointerIcon.STYLE_NOT_SPECIFIED;
-            case PFLAG3_POINTER_ICON_NULL:
-                return PointerIcon.STYLE_NULL;
-            case PFLAG3_POINTER_ICON_CUSTOM:
-                return PointerIcon.STYLE_CUSTOM;
-            default:
-                return ((value - PFLAG3_POINTER_ICON_VALUE_START) >> PFLAG3_POINTER_ICON_LSHIFT)
-                        + PointerIcon.STYLE_ARROW;
-        }
+    /**
+     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
+     * The default implementation does not care the location or event types, but some subclasses
+     * may use it (such as WebViews).
+     * @param event The MotionEvent from a mouse
+     * @param x The x position of the event, local to the view
+     * @param y The y position of the event, local to the view
+     * @see PointerIcon
+     */
+    public PointerIcon getPointerIcon(MotionEvent event, float x, float y) {
+        return mPointerIcon;
     }
 
-    /** @hide */
-    public void setPointerShape(int pointerShape) {
-        int newValue;
-        if (pointerShape == PointerIcon.STYLE_NOT_SPECIFIED) {
-            newValue = PFLAG3_POINTER_ICON_NOT_SPECIFIED;
-        } else if (pointerShape == PointerIcon.STYLE_NULL) {
-            newValue = PFLAG3_POINTER_ICON_NULL;
-        } else if (pointerShape == PointerIcon.STYLE_CUSTOM) {
-            newValue = PFLAG3_POINTER_ICON_CUSTOM;
-        } else if (pointerShape >= PointerIcon.STYLE_ARROW
-                && pointerShape <= PointerIcon.STYLE_GRABBING) {
-            newValue = ((pointerShape - PointerIcon.STYLE_ARROW) << PFLAG3_POINTER_ICON_LSHIFT)
-                    + PFLAG3_POINTER_ICON_VALUE_START;
-        } else {
-            Log.w(VIEW_LOG_TAG, "Invalid pointer shape " + pointerShape + " is specified.");
-            return;
-        }
-        if (newValue != (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK)) {
-            mPrivateFlags3 = (mPrivateFlags3 & ~PFLAG3_POINTER_ICON_MASK) | newValue;
-        }
+    /**
+     * Set the pointer icon for the current view.
+     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
+     */
+    public void setPointerIcon(PointerIcon pointerIcon) {
+        mPointerIcon = pointerIcon;
     }
 
     //
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0f7d296..cd93dab 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1715,9 +1715,8 @@
         return false;
     }
 
-    /** @hide */
     @Override
-    public int getPointerShape(MotionEvent event, float x, float y) {
+    public PointerIcon getPointerIcon(MotionEvent event, float x, float y) {
         // Check what the child under the pointer says about the pointer.
         final int childrenCount = mChildrenCount;
         if (childrenCount != 0) {
@@ -1731,9 +1730,9 @@
                         ? children[childIndex] : preorderedList.get(childIndex);
                 PointF point = getLocalPoint();
                 if (isTransformedTouchPointInView(x, y, child, point)) {
-                    final int pointerShape = child.getPointerShape(event, point.x, point.y);
-                    if (pointerShape != PointerIcon.STYLE_NOT_SPECIFIED) {
-                        return pointerShape;
+                    final PointerIcon pointerIcon = child.getPointerIcon(event, point.x, point.y);
+                    if (pointerIcon != null) {
+                        return pointerIcon;
                     }
                     break;
                 }
@@ -1742,7 +1741,7 @@
 
         // The pointer is not a child or the child has no preferences, returning the default
         // implementation.
-        return super.getPointerShape(event, x, y);
+        return super.getPointerIcon(event, x, y);
     }
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 12cf66e..faf2640 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -332,6 +332,7 @@
     private int mFpsNumFrames;
 
     private int mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
+    private PointerIcon mCustomPointerIcon = null;
 
     /**
      * see {@link #playSoundEffect(int)}
@@ -4210,16 +4211,23 @@
                 final float y = event.getY();
                 if (event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT
                         && x >= 0 && x < mView.getWidth() && y >= 0 && y < mView.getHeight()) {
-                    int pointerShape = mView.getPointerShape(event, x, y);
-                    if (pointerShape == PointerIcon.STYLE_NOT_SPECIFIED) {
-                        pointerShape = PointerIcon.STYLE_DEFAULT;
-                    }
+                    PointerIcon pointerIcon = mView.getPointerIcon(event, x, y);
+                    int pointerShape = (pointerIcon != null) ?
+                            pointerIcon.getStyle() : PointerIcon.STYLE_DEFAULT;
 
-                    if (mPointerIconShape != pointerShape) {
-                        mPointerIconShape = pointerShape;
-                        final InputDevice inputDevice = event.getDevice();
-                        if (inputDevice != null) {
-                            inputDevice.setPointerShape(pointerShape);
+                    final InputDevice inputDevice = event.getDevice();
+                    if (inputDevice != null) {
+                        if (mPointerIconShape != pointerShape) {
+                            mPointerIconShape = pointerShape;
+                            if (mPointerIconShape != PointerIcon.STYLE_CUSTOM) {
+                                mCustomPointerIcon = null;
+                                inputDevice.setPointerShape(pointerShape);
+                            }
+                        }
+                        if (mPointerIconShape == PointerIcon.STYLE_CUSTOM &&
+                                !pointerIcon.equals(mCustomPointerIcon)) {
+                            mCustomPointerIcon = pointerIcon;
+                            inputDevice.setCustomPointerIcon(mCustomPointerIcon);
                         }
                     }
                 } else if (event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index d6bc27c..2e884cc 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1171,6 +1171,16 @@
          */
         public static final int PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY = 0x00004000;
 
+        /**
+         * Flag to indicate that this window is not expected to be replaced across
+         * configuration change triggered activity relaunches. In general the WindowManager
+         * expects Windows to be replaced after relaunch, and thus it will preserve their surfaces
+         * until the replacement is ready to show in order to prevent visual glitch. However
+         * some windows, such as PopupWindows expect to be cleared across configuration change,
+         * and thus should hint to the WindowManager that it should not wait for a replacement.
+         * @hide
+         */
+        public static final int PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH = 0x00008000;
 
         /**
          * Control flags that are private to the platform.
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index b1a8479..01bfbb5 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -446,6 +446,13 @@
          */
         public void switchKeyboardLayout(int deviceId, int direction);
 
+        /**
+         * Switch the input method, to be precise, input method subtype.
+         *
+         * @param forwardDirection {@code true} to rotate in a forward direction.
+         */
+        public void switchInputMethod(boolean forwardDirection);
+
         public void shutdown(boolean confirm);
         public void rebootSafeMode(boolean confirm);
 
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 329d1b0..5e07347 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -54,6 +54,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -2209,7 +2210,7 @@
             p.println("  mCurrentTextBoxAttribute: null");
         }
         p.println("  mServedInputConnection=" + mServedInputConnection);
-        p.println("  mCompletions=" + mCompletions);
+        p.println("  mCompletions=" + Arrays.toString(mCompletions));
         p.println("  mCursorRect=" + mCursorRect);
         p.println("  mCursorSelStart=" + mCursorSelStart
                 + " mCursorSelEnd=" + mCursorSelEnd
diff --git a/core/java/android/view/inputmethod/InputMethodManagerInternal.java b/core/java/android/view/inputmethod/InputMethodManagerInternal.java
index c22127b..ce9908c 100644
--- a/core/java/android/view/inputmethod/InputMethodManagerInternal.java
+++ b/core/java/android/view/inputmethod/InputMethodManagerInternal.java
@@ -26,5 +26,10 @@
      * Called by the power manager to tell the input method manager whether it
      * should start watching for wake events.
      */
-    public void setInteractive(boolean interactive);
+    void setInteractive(boolean interactive);
+
+    /**
+     * Called by the window manager to let the input method manager rotate the input method.
+     */
+    void switchInputMethod(boolean forwardDirection);
 }
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 607e955..ee73092 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1643,8 +1643,16 @@
 
         boolean handled = false;
         int action = event.getAction();
+        if (KeyEvent.isConfirmKey(keyCode)
+                && event.hasNoModifiers() && action == KeyEvent.ACTION_UP) {
+            handled = resurrectSelectionIfNeeded();
+            if (!handled && event.getRepeatCount() == 0 && getChildCount() > 0) {
+                keyPressed();
+                handled = true;
+            }
+        }
 
-        if (action != KeyEvent.ACTION_UP) {
+        if (!handled && action != KeyEvent.ACTION_UP) {
             switch (keyCode) {
                 case KeyEvent.KEYCODE_DPAD_LEFT:
                     if (event.hasNoModifiers()) {
@@ -1674,28 +1682,6 @@
                     }
                     break;
 
-                case KeyEvent.KEYCODE_DPAD_CENTER:
-                case KeyEvent.KEYCODE_ENTER:
-                    if (event.hasNoModifiers()) {
-                        handled = resurrectSelectionIfNeeded();
-                        if (!handled
-                                && event.getRepeatCount() == 0 && getChildCount() > 0) {
-                            keyPressed();
-                            handled = true;
-                        }
-                    }
-                    break;
-
-                case KeyEvent.KEYCODE_SPACE:
-                    if (mPopup == null || !mPopup.isShowing()) {
-                        if (event.hasNoModifiers()) {
-                            handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_DOWN);
-                        } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
-                            handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_UP);
-                        }
-                    }
-                    break;
-
                 case KeyEvent.KEYCODE_PAGE_UP:
                     if (event.hasNoModifiers()) {
                         handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_UP);
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 53ca6d1..064808b 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2180,8 +2180,17 @@
 
         boolean handled = false;
         int action = event.getAction();
+        if (KeyEvent.isConfirmKey(keyCode)
+                && event.hasNoModifiers() && action == KeyEvent.ACTION_UP) {
+            handled = resurrectSelectionIfNeeded();
+            if (!handled && event.getRepeatCount() == 0 && getChildCount() > 0) {
+                keyPressed();
+                handled = true;
+            }
+        }
 
-        if (action != KeyEvent.ACTION_UP) {
+
+        if (!handled && action != KeyEvent.ACTION_UP) {
             switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_UP:
                 if (event.hasNoModifiers()) {
@@ -2229,29 +2238,6 @@
                 }
                 break;
 
-            case KeyEvent.KEYCODE_DPAD_CENTER:
-            case KeyEvent.KEYCODE_ENTER:
-                if (event.hasNoModifiers()) {
-                    handled = resurrectSelectionIfNeeded();
-                    if (!handled
-                            && event.getRepeatCount() == 0 && getChildCount() > 0) {
-                        keyPressed();
-                        handled = true;
-                    }
-                }
-                break;
-
-            case KeyEvent.KEYCODE_SPACE:
-                if (mPopup == null || !mPopup.isShowing()) {
-                    if (event.hasNoModifiers()) {
-                        handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_DOWN);
-                    } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
-                        handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_UP);
-                    }
-                    handled = true;
-                }
-                break;
-
             case KeyEvent.KEYCODE_PAGE_UP:
                 if (event.hasNoModifiers()) {
                     handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_UP);
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 7b9de79..f4c343a 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -16,6 +16,8 @@
 
 package android.widget;
 
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
+
 import com.android.internal.R;
 
 import android.annotation.NonNull;
@@ -1311,6 +1313,8 @@
             p.width = mLastWidth = mWidth;
         }
 
+        p.privateFlags = PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
+
         // Used for debugging.
         p.setTitle("PopupWindow:" + Integer.toHexString(hashCode()));
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5574f86..17c803f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5955,15 +5955,12 @@
         return mLayout != null ? mLayout.getHeight() : 0;
     }
 
-    /**
-     * @hide
-     */
     @Override
-    public int getPointerShape(MotionEvent event, float x, float y) {
+    public PointerIcon getPointerIcon(MotionEvent event, float x, float y) {
         if (isTextSelectable() || isTextEditable()) {
-            return PointerIcon.STYLE_TEXT;
+            return PointerIcon.getSystemIcon(mContext, PointerIcon.STYLE_TEXT);
         }
-        return super.getPointerShape(event, x, y);
+        return super.getPointerIcon(event, x, y);
     }
 
     @Override
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index e405564..f6b8e91 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -17,11 +17,13 @@
 package com.android.internal.policy;
 
 import com.android.internal.R;
+import com.android.internal.policy.PhoneWindow.PhoneWindowMenuCallback;
 import com.android.internal.view.FloatingActionMode;
 import com.android.internal.view.RootViewSurfaceTaker;
 import com.android.internal.view.StandaloneActionMode;
 import com.android.internal.view.menu.ContextMenuBuilder;
 import com.android.internal.view.menu.MenuHelper;
+import com.android.internal.view.menu.MenuPresenter;
 import com.android.internal.widget.ActionBarContextView;
 import com.android.internal.widget.BackgroundFallback;
 import com.android.internal.widget.DecorCaptionView;
@@ -684,9 +686,10 @@
         }
 
         // Reuse the context menu builder.
+        final PhoneWindowMenuCallback callback = mWindow.mContextMenuCallback;
         if (mWindow.mContextMenu == null) {
             mWindow.mContextMenu = new ContextMenuBuilder(getContext());
-            mWindow.mContextMenu.setCallback(mWindow.mContextMenuCallback);
+            mWindow.mContextMenu.setCallback(callback);
         } else {
             mWindow.mContextMenu.clearAll();
         }
@@ -698,9 +701,11 @@
             helper = mWindow.mContextMenu.showDialog(originalView, originalView.getWindowToken());
         }
 
-        if (helper != null) {
-            helper.setPresenterCallback(mWindow.mContextMenuCallback);
-        }
+        // If it's a dialog, the callback needs to handle showing sub-menus.
+        // Either way, the callback is required for propagating selection to
+        // Context.onContextMenuItemSelected().
+        callback.setShowDialogForSubmenu(!isPopup);
+        helper.setPresenterCallback(callback);
 
         mWindow.mContextMenuHelper = helper;
         return helper != null;
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 86bd782..1e9035b 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -127,7 +127,7 @@
      * Simple callback used by the context menu and its submenus. The options
      * menu submenus do not use this (their behavior is more complex).
      */
-    final DialogMenuCallback mContextMenuCallback = new DialogMenuCallback(FEATURE_CONTEXT_MENU);
+    final PhoneWindowMenuCallback mContextMenuCallback = new PhoneWindowMenuCallback(this);
 
     final TypedValue mMinWidthMajor = new TypedValue();
     final TypedValue mMinWidthMinor = new TypedValue();
@@ -3592,27 +3592,34 @@
      * <li> Calls back to the callback's onMenuItemSelected when an item is
      * selected.
      */
-    private final class DialogMenuCallback implements MenuBuilder.Callback, MenuPresenter.Callback {
-        private int mFeatureId;
+    public static final class PhoneWindowMenuCallback
+            implements MenuBuilder.Callback, MenuPresenter.Callback {
+        private static final int FEATURE_ID = FEATURE_CONTEXT_MENU;
+
+        private final PhoneWindow mWindow;
+
         private MenuDialogHelper mSubMenuHelper;
 
-        public DialogMenuCallback(int featureId) {
-            mFeatureId = featureId;
+        private boolean mShowDialogForSubmenu;
+
+        public PhoneWindowMenuCallback(PhoneWindow window) {
+            mWindow = window;
         }
 
+        @Override
         public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
             if (menu.getRootMenu() != menu) {
                 onCloseSubMenu(menu);
             }
 
             if (allMenusAreClosing) {
-                Callback callback = getCallback();
-                if (callback != null && !isDestroyed()) {
-                    callback.onPanelClosed(mFeatureId, menu);
+                final Callback callback = mWindow.getCallback();
+                if (callback != null && !mWindow.isDestroyed()) {
+                    callback.onPanelClosed(FEATURE_ID, menu);
                 }
 
-                if (menu == mContextMenu) {
-                    dismissContextMenu();
+                if (menu == mWindow.mContextMenu) {
+                    mWindow.dismissContextMenu();
                 }
 
                 // Dismiss the submenu, if it is showing
@@ -3623,33 +3630,45 @@
             }
         }
 
-        public void onCloseSubMenu(MenuBuilder menu) {
-            Callback callback = getCallback();
-            if (callback != null && !isDestroyed()) {
-                callback.onPanelClosed(mFeatureId, menu.getRootMenu());
+        private void onCloseSubMenu(MenuBuilder menu) {
+            final Callback callback = mWindow.getCallback();
+            if (callback != null && !mWindow.isDestroyed()) {
+                callback.onPanelClosed(FEATURE_ID, menu.getRootMenu());
             }
         }
 
+        @Override
         public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
-            Callback callback = getCallback();
-            return (callback != null && !isDestroyed())
-                    && callback.onMenuItemSelected(mFeatureId, item);
+            final Callback callback = mWindow.getCallback();
+            return callback != null && !mWindow.isDestroyed()
+                    && callback.onMenuItemSelected(FEATURE_ID, item);
         }
 
+        @Override
         public void onMenuModeChange(MenuBuilder menu) {
         }
 
+        @Override
         public boolean onOpenSubMenu(MenuBuilder subMenu) {
-            if (subMenu == null) return false;
+            if (subMenu == null) {
+                return false;
+            }
 
             // Set a simple callback for the submenu
             subMenu.setCallback(this);
 
-            // The window manager will give us a valid window token
-            mSubMenuHelper = new MenuDialogHelper(subMenu);
-            mSubMenuHelper.show(null);
+            if (mShowDialogForSubmenu) {
+                // The window manager will give us a valid window token
+                mSubMenuHelper = new MenuDialogHelper(subMenu);
+                mSubMenuHelper.show(null);
+                return true;
+            }
 
-            return true;
+            return false;
+        }
+
+        public void setShowDialogForSubmenu(boolean enabled) {
+            mShowDialogForSubmenu = enabled;
         }
     }
 
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index 6a5f6d8..c2adc42 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -242,13 +242,13 @@
     @Override
     public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
         if (subMenu.hasVisibleItems()) {
-            MenuPopupHelper subPopup = new MenuPopupHelper(
-                    mContext, subMenu, mShownAnchorView, mOverflowOnly, mPopupStyleAttr,
-                    mPopupStyleRes);
+            final MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu,
+                    mShownAnchorView, mOverflowOnly, mPopupStyleAttr, mPopupStyleRes);
             subPopup.setPresenterCallback(mPresenterCallback);
             subPopup.setForceShowIcon(mAdapter.getForceShowIcon());
 
-            if (subPopup.tryShow()) {
+            // Show the new sub-menu popup at the same location as this popup.
+            if (subPopup.tryShow(mXOffset, mYOffset)) {
                 if (mPresenterCallback != null) {
                     mPresenterCallback.onOpenSubMenu(subMenu);
                 }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 6c223c3..e38d82f 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -64,6 +64,11 @@
     private static final boolean DEBUG = false;
 
     /**
+     * The key to identify when the lock pattern enabled flag is being acccessed for legacy reasons.
+     */
+    public static final String LEGACY_LOCK_PATTERN_ENABLED = "legacy_lock_pattern_enabled";
+
+    /**
      * The number of incorrect attempts before which we fall back on an alternative
      * method of verifying the user, and resetting their lock pattern.
      */
@@ -1014,6 +1019,19 @@
         return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId);
     }
 
+    @Deprecated
+    public boolean isLegacyLockPatternEnabled(int userId) {
+        // Note: this value should default to {@code true} to avoid any reset that might result.
+        // We must use a special key to read this value, since it will by default return the value
+        // based on the new logic.
+        return getBoolean(LEGACY_LOCK_PATTERN_ENABLED, true, userId);
+    }
+
+    @Deprecated
+    public void setLegacyLockPatternEnabled(int userId) {
+        setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, true, userId);
+    }
+
     private boolean isLockPatternEnabled(int mode, int userId) {
         return mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
                 && savedPatternExists(userId);
diff --git a/core/jni/android_view_PointerIcon.cpp b/core/jni/android_view_PointerIcon.cpp
index d7e2c02..71be52e 100644
--- a/core/jni/android_view_PointerIcon.cpp
+++ b/core/jni/android_view_PointerIcon.cpp
@@ -65,33 +65,34 @@
         return OK;
     }
 
-    jobject loadedPointerIconObj = env->CallObjectMethod(pointerIconObj,
-            gPointerIconClassInfo.load, contextObj);
-    if (env->ExceptionCheck() || !loadedPointerIconObj) {
+    ScopedLocalRef<jobject> loadedPointerIconObj(env, env->CallObjectMethod(pointerIconObj,
+            gPointerIconClassInfo.load, contextObj));
+    if (env->ExceptionCheck() || !loadedPointerIconObj.get()) {
         ALOGW("An exception occurred while loading a pointer icon.");
         LOGW_EX(env);
         env->ExceptionClear();
         return UNKNOWN_ERROR;
     }
+    return android_view_PointerIcon_getLoadedIcon(env, loadedPointerIconObj.get(), outPointerIcon);
+}
 
-    outPointerIcon->style = env->GetIntField(loadedPointerIconObj,
-            gPointerIconClassInfo.mStyle);
-    outPointerIcon->hotSpotX = env->GetFloatField(loadedPointerIconObj,
-            gPointerIconClassInfo.mHotSpotX);
-    outPointerIcon->hotSpotY = env->GetFloatField(loadedPointerIconObj,
-            gPointerIconClassInfo.mHotSpotY);
+status_t android_view_PointerIcon_getLoadedIcon(JNIEnv* env, jobject pointerIconObj,
+        PointerIcon* outPointerIcon) {
+    outPointerIcon->style = env->GetIntField(pointerIconObj, gPointerIconClassInfo.mStyle);
+    outPointerIcon->hotSpotX = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotX);
+    outPointerIcon->hotSpotY = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotY);
 
-    jobject bitmapObj = env->GetObjectField(loadedPointerIconObj, gPointerIconClassInfo.mBitmap);
-    if (bitmapObj) {
-        GraphicsJNI::getSkBitmap(env, bitmapObj, &(outPointerIcon->bitmap));
-        env->DeleteLocalRef(bitmapObj);
+    ScopedLocalRef<jobject> bitmapObj(
+            env, env->GetObjectField(pointerIconObj, gPointerIconClassInfo.mBitmap));
+    if (bitmapObj.get()) {
+        GraphicsJNI::getSkBitmap(env, bitmapObj.get(), &(outPointerIcon->bitmap));
     }
 
     ScopedLocalRef<jobjectArray> bitmapFramesObj(env, reinterpret_cast<jobjectArray>(
-            env->GetObjectField(loadedPointerIconObj, gPointerIconClassInfo.mBitmapFrames)));
+            env->GetObjectField(pointerIconObj, gPointerIconClassInfo.mBitmapFrames)));
     if (bitmapFramesObj.get()) {
         outPointerIcon->durationPerFrame = env->GetIntField(
-                loadedPointerIconObj, gPointerIconClassInfo.mDurationPerFrame);
+                pointerIconObj, gPointerIconClassInfo.mDurationPerFrame);
         jsize size = env->GetArrayLength(bitmapFramesObj.get());
         outPointerIcon->bitmapFrames.resize(size);
         for (jsize i = 0; i < size; ++i) {
@@ -100,7 +101,6 @@
         }
     }
 
-    env->DeleteLocalRef(loadedPointerIconObj);
     return OK;
 }
 
diff --git a/core/jni/android_view_PointerIcon.h b/core/jni/android_view_PointerIcon.h
index ca08085..00bdfb4 100644
--- a/core/jni/android_view_PointerIcon.h
+++ b/core/jni/android_view_PointerIcon.h
@@ -97,6 +97,11 @@
 extern status_t android_view_PointerIcon_load(JNIEnv* env,
         jobject pointerIconObj, jobject contextObj, PointerIcon* outPointerIcon);
 
+/* Obtain the data of pointerIconObj and put to outPointerIcon. */
+extern status_t android_view_PointerIcon_getLoadedIcon(JNIEnv* env, jobject pointerIconObj,
+        PointerIcon* outPointerIcon);
+
+
 /* Loads the bitmap associated with a pointer icon by style.
  * If pointerIconObj is NULL, returns OK and a pointer icon with POINTER_ICON_STYLE_NULL. */
 extern status_t android_view_PointerIcon_loadSystemIcon(JNIEnv* env,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1127197..de7f6ed 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -369,6 +369,22 @@
     <protected-broadcast android:name="ScheduleConditionProvider.EVALUATE" />
     <protected-broadcast android:name="wifi_scan_available" />
 
+    <protected-broadcast android:name="action.cne.started" />
+    <protected-broadcast android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+    <protected-broadcast android:name="android.content.jobscheduler.JOB_DEADLINE_EXPIRED" />
+    <protected-broadcast android:name="android.intent.action.ACTION_UNSOL_RESPONSE_OEM_HOOK_RAW" />
+    <protected-broadcast android:name="android.location.HIGH_POWER_REQUEST_CHANGE" />
+    <protected-broadcast android:name="android.location.HIGH_POWER_REQUEST_CHANGE" />
+    <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_SUPL" />
+    <protected-broadcast android:name="android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED" />
+    <protected-broadcast android:name="android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED" />
+    <protected-broadcast android:name="android.os.storage.action.VOLUME_STATE_CHANGED" />
+    <protected-broadcast android:name="com.android.server.action.UPDATE_TWILIGHT_STATE" />
+    <protected-broadcast android:name="com.android.server.device_idle.STEP_IDLE_STATE" />
+    <protected-broadcast android:name="com.android.server.device_idle.STEP_LIGHT_IDLE_STATE" />
+    <protected-broadcast android:name="com.android.server.Wifi.action.TOGGLE_PNO" />
+    <protected-broadcast android:name="intent.action.ACTION_RF_BAND_INFO" />
+
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
     <!-- ====================================================================== -->
@@ -643,14 +659,14 @@
 
     <!-- Allows an application to access the IMS call service: making and
          modifying a call
-        <p>Protection level: signature|system
+        <p>Protection level: signature|privileged
         @hide
     -->
     <permission android:name="android.permission.ACCESS_IMS_CALL_SERVICE"
         android:permissionGroup="android.permission-group.PHONE"
         android:label="@string/permlab_accessImsCallService"
         android:description="@string/permdesc_accessImsCallService"
-        android:protectionLevel="signature|system" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to read the user's call log.
          <p class="note"><strong>Note:</strong> If your app uses the
@@ -927,7 +943,7 @@
     <!-- @SystemApi @hide Allows an application to modify cell broadcasts through the content provider.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MODIFY_CELL_BROADCASTS"
-                android:protectionLevel="signature|system" />
+                android:protectionLevel="signature|privileged" />
 
     <!-- =============================================================== -->
     <!-- Permissions for setting the device alarm                        -->
@@ -948,16 +964,16 @@
     <eat-comment />
 
     <!-- Allows an application to modify and remove existing voicemails in the system
-        <p>Protection level: system|signature
+        <p>Protection level: signature|privileged
     -->
     <permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to read voicemails in the system.
-         <p>Protection level: system|signature
+         <p>Protection level: signature|privileged
     -->
     <permission android:name="com.android.voicemail.permission.READ_VOICEMAIL"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ======================================= -->
     <!-- Permissions for accessing location info -->
@@ -1093,7 +1109,7 @@
          allow or disallow phonebook access or message access.
          This is not available to third party applications. -->
     <permission android:name="android.permission.BLUETOOTH_PRIVILEGED"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Control access to email providers exclusively for Bluetooth
          @hide
@@ -1331,26 +1347,26 @@
          corresponds to a device SIM.
          @hide -->
     <permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_CALL_PROVIDER.
          @hide -->
     <permission android:name="android.permission.REGISTER_CALL_PROVIDER"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_CONNECTION_MANAGER
          @hide -->
     <permission android:name="android.permission.REGISTER_CONNECTION_MANAGER"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.InCallService},
          to ensure that only the system can bind to it.
-         <p>Protection level: system|signature
+         <p>Protection level: signature|privileged
     -->
     <permission android:name="android.permission.BIND_INCALL_SERVICE"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.ConnectionService},
          to ensure that only the system can bind to it.
@@ -1359,24 +1375,24 @@
          @SystemApi
          @hide -->
     <permission android:name="android.permission.BIND_CONNECTION_SERVICE"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Must be required by a {@link android.telecom.ConnectionService},
          to ensure that only the system can bind to it.
-         <p>Protection level: system|signature
+         <p>Protection level: signature|privileged
     -->
     <permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to control the in-call experience.
          @hide -->
     <permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an application to receive STK related commands.
          @hide -->
     <permission android:name="android.permission.RECEIVE_STK_COMMANDS"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- ================================== -->
     <!-- Permissions for sdcard interaction -->
@@ -1731,12 +1747,12 @@
     <!-- @SystemApi Allows mounting and unmounting file systems for removable storage.
     <p>Not for use by third-party applications.-->
     <permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows formatting file systems for removable storage.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @hide -->
     <permission android:name="android.permission.STORAGE_INTERNAL"
@@ -2399,7 +2415,7 @@
          access the network and acquire wakelocks.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Permission an application must hold in order to use
          {@link android.provider.Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}.
@@ -2613,7 +2629,7 @@
 
     <!-- Allows managing (adding, removing) fingerprint templates. Reserved for the system. @hide -->
     <permission android:name="android.permission.MANAGE_FINGERPRINT"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- Allows an app to reset fingerprint attempt counter. Reserved for the system. @hide -->
     <permission android:name="android.permission.RESET_FINGERPRINT_LOCKOUT"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index eaf82fb..cf4f18d 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Opgedateer deur jou administrateur"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Deur jou administrateur uitgevee"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Om batterylewe te help verbeter, verminder batterybespaarder jou toestel se werkverrigting en beperk vibrasie, liggingdienste en die meeste agtergronddata. E-pos, boodskappe en ander programme wat op sinkronisering staatmaak, sal dalk nie opdateer tensy jy hulle oopmaak nie.\n\nBatterybespaarder skakel outomaties af wanneer jou toestel besig is om te laai."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Geblokkeer: Moet nooit hierdie kennisgewings wys nie"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Laag: Wys sonder klank aan die onderkant van die kennisgewinglys"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normaal: Wys hierdie kennisgewings sonder klank"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> gekies</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 03dbcae..4a35fb4 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"በአስተዳዳሪዎ ተዘምኗል"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"በእርስዎ አስተዳዳሪ ተሰርዟል"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"የባትሪ ዕድሜን ለማሻሻል ማገዝ እንዲቻል፣ ኢሜይል፣ መልዕክት አላላክ እና ሌሎች በማመሳሰል ላይ የሚመረኮዙ መተግበሪያዎች እርስዎ ካልከፈቱዋቸው በቀር አይዘምኑም።\n\nየባትሪ ኃይል ቆጣቢ የእርስዎ መሣሪያ ኃይል በሚሞላበት ጊዜ በራስ-ሰር ይጠፋል።"</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"የታገደ፦ እነኝህን ማሳወቂያዎች ፈፅሞ አታሳይ"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"ዝቅተኛ፦ በጸጥታ የማሳወቂያ ዝርዝር የታችኛውን ክፍል አሳይ"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"መደበኛ፦ በጸጥታ እነኝህን ማሳወቂያዎች አሳይ"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ተመርጠዋል</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"የተለያዩ"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index b103b1b..c18fc4a 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1476,6 +1476,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"تم التحديث بواسطة المشرف"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"تم حذف الحزمة عن طريق المشرف"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"للمساعدة في تحسين عمر البطارية، يساعد موفر البطارية في تقليل أداء الجهاز ويفرض قيدًا على الاهتزاز وخدمات الموقع ومعظم بيانات الخلفية. قد لا يتم تحديث البريد الإلكتروني والمراسلة والتطبيقات الأخرى التي تعتمد على المزامنة ما لم تفتحها.\n\nيتم إيقاف موفر البطارية تلقائيًا أثناء شحن الجهاز."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"الأهمية"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"محظور: عدم عرض هذه الإشعارات مطلقًا"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"منخفض الأهمية: عرض بأسفل قائمة الإشعارات وبدون تنبيه صوتي"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"عادي: عرض هذه الإشعارات بدون تنبيه صوتي"</string>
@@ -1582,4 +1583,6 @@
       <item quantity="one">تم تحديد <xliff:g id="COUNT_0">%1$d</xliff:g> عنصر</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"متنوعة"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"لقد عيَّنت أهمية هذه الإشعارات."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"هذه الرسالة مهمة نظرًا لأهمية الأشخاص المعنيين."</string>
 </resources>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 920068b..5de0b59 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Sizin administrator tərəfindən yeniləndi"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratorunuz tərəfindən silinib"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Batareyanın istismar müddətini təkmilləşdirmək üçün batareya qənaəti cihazınızın məhsuldarlığını azaldır və titrətmə, məkan xidmətləri və ən son fon məlumatlarını məhdudlaşdırır. Sinxronlaşmaya arxayın olan e-poçt, mesajlaşma və digər proqramlar siz onları açmayana kimi yenilənməyə bilər.\n\nCihazınız doldurulan zaman batareya qənaəti avtomatik olaraq sönür."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Əhəmiyyət"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blok edildi: Bu bildirişləri heç vaxt göstərməyin"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Alçaq: Bildirişlər siyahısının aşağısında səssiz göstərin"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: Bu bildişləri səssiz göstərin"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> seçilib</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Müxtəlif"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Bildirişlərin əhəmiyyətini Siz ayarlaryırsınız."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"İnsanlar cəlb olunduğu üçün bu vacibdir."</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 88b261e..fc0317a 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Актуализирано от администратора ви"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Изтрито от администратора ви"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"С цел удължаване на живота на батерията режимът за запазването й намалява ефективността на устройството ви и ограничава вибрирането, услугите за местоположение и повечето данни на заден план. Приложенията за електронна поща, съобщения и др., които разчитат на синхронизиране, може да не се актуализират, освен ако не ги отворите.\n\nРежимът за запазване на батерията се изключва автоматично, когато устройството ви се зарежда."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Важност"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Блокирано: Тези известия никога да не се показват"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Маловажно: Показване без звуков сигнал в долната част на списъка с известия"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Нормално: Тези известия да се показват без звуков сигнал"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one">Избрахте <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Други"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Зададохте важността на тези известия."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"Това е важно заради участващите хора."</string>
 </resources>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 91244e6..bbec615 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"আপনার প্রশাসক দ্বারা আপডেট করা হয়েছে"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"আপনার প্রশাসক দ্বারা মুছে ফেলা হয়েছে"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"ব্যাটরির লাইফ উন্নত করতে সহায়তা করতে, ব্যাটারি সাশ্রয়কারী আপনার ডিভাইসের কার্যসম্পাদনা হ্রাস করে এবং কম্পন, অবস্থান পরিষেবাসমূহ এবং অধিকাংশ ব্যাকগ্রাউন্ড ডেটা সীমিত করে৷ ইমেল, বার্তাপ্রেরণ এবং অন্যান্য অ্যাপ্লিকেশানগুলিকে যেগুলি সিঙ্কের উপর নির্ভর করে সেগুলিকে আপনি না খোলা পর্যন্ত নাও আপডেট হতে পারে৷\n\nআপনার ডিভাইসটিকে যখন চার্জ করা হয় তখন ব্যাটারি সাশ্রয়কারী স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যায়৷"</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"অবরুদ্ধ: এই বিজ্ঞপ্তিগুলি কখনই দেখানো হবে না"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"নিম্ন: বিজ্ঞপ্তি তালিকার নীচের অংশে নিঃশব্দে প্রদর্শন করা হয়"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"সাধারন: এই বিজ্ঞপ্তিগুলি নিঃশব্দে প্রদর্শন করা হয়"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি নির্বাচন করা হয়েছে</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"বিবিধ"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 0d2b46c..13109f5 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"L\'administrador l\'ha actualitzat"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"L\'administrador ho ha suprimit"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Per tal d\'augmentar la durada de la bateria, la funció d\'estalvi de bateria redueix el rendiment del dispositiu i en limita la vibració i la majoria de dades en segon pla. És possible que el correu electrònic, la missatgeria i la resta d\'aplicacions que se sincronitzen amb freqüència no s\'actualitzin llevat que les obris.\n\nL\'estalvi de bateria es desactiva automàticament mentre el dispositiu s\'està carregant."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloquejada: no mostra mai aquestes notificacions"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Baixa: mostra de manera silenciosa a la part inferior de la llista de notificacions"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: mostra aquestes notificacions de manera silenciosa"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one">Seleccionats: <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Altres"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 4c554bc..ea94aff 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1458,6 +1458,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Aktualizováno administrátorem"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Smazáno administrátorem"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Spořič baterie za účelem prodloužení výdrže baterie snižuje výkon zařízení a omezuje vibrace, služby určování polohy a většinu dat na pozadí. E-mail, aplikace pro zasílání zpráv a další aplikace, které používají synchronizaci, se nemusejí aktualizovat, dokud je neotevřete.\n\nPři nabíjení zařízení se spořič baterie automaticky vypne."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blokováno: Tato oznámení nikdy nezobrazovat"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Nízká: Tato oznámení zobrazovat na konci seznamu bez zvukového upozornění"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normální: Tato oznámení zobrazovat bez zvukového upozornění"</string>
@@ -1546,4 +1548,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> položka</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Různé"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 850b8a2..73e9990 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -998,11 +998,11 @@
     <string name="sms_control_no" msgid="625438561395534982">"Afvis"</string>
     <string name="sms_short_code_confirm_message" msgid="1645436466285310855">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vil sende en besked til &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
     <string name="sms_short_code_details" msgid="5873295990846059400">"Dette "<b>"kan medføre gebyrer"</b>" på din mobilkonto."</string>
-    <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Dette vil medføre gebyrer på din mobilkonto."</b></string>
+    <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Dette kan koste mere end almindelig sms-takst."</b></string>
     <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Send"</string>
     <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Annuller"</string>
     <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Husk mit valg"</string>
-    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Du kan ændre dette senere i Indstillinger &gt; Apps"</string>
+    <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Du kan altid ændre dette i Indstillinger &gt; Apps"</string>
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Tillad altid"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Tillad aldrig"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"SIM-kort blev fjernet"</string>
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Opdateret af administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Slettet af din administrator"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Batterisparefunktionen hjælper med at forlænge batteriets levetid ved at reducere enhedens ydeevne og begrænse vibration, placeringstjenester og det meste baggrundsdata. E-mail, beskedfunktioner og andre apps, der benytter synkronisering, opdateres muligvis ikke, medmindre du åbner dem.\n\nBatterisparefunktionen slukker automatisk, når enheden oplader."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blokeret: Vis aldrig disse underretninger"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Lav: Vis lydløst nederst på listen over underretninger"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: Vis disse underretninger lydløst"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valgt</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index ab45504..a1bd45c 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Von Ihrem Administrator aktualisiert"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Von Ihrem Administrator gelöscht"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Der Energiesparmodus schont den Akku, indem er die Leistung des Geräts reduziert und die Vibrationsfunktion sowie die meisten Hintergrunddatenaktivitäten einschränkt. E-Mail, SMS/MMS und andere Apps, die auf Ihrem Gerät synchronisiert werden, werden möglicherweise erst nach dem Öffnen aktualisiert.\n\nDer Energiesparmodus wird automatisch deaktiviert, wenn Ihr Gerät aufgeladen wird."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blockiert: Keine Benachrichtigungen anzeigen"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Niedrig: Benachrichtigungen ganz unten in der Benachrichtigungsliste und ohne Ton anzeigen"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: Benachrichtigungen ohne Ton anzeigen"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ausgewählt</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Sonstige"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index d5fdd29..f0b1bf9 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ενημερώθηκε από το διαχειριστή σας"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Διαγράφηκε από το διαχειριστή σας"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Προκειμένου να βελτιώσει τη διάρκεια ζωής της μπαταρίας σας, η Εξοικονόμηση μπαταρίας μειώνει την απόδοση της συσκευής σας και περιορίζει λειτουργίες όπως η δόνηση, οι υπηρεσίες τοποθεσίας και τα περισσότερα δεδομένα παρασκηνίου. Το ηλεκτρονικό ταχυδρομείο, η ανταλλαγή μηνυμάτων και άλλες εφαρμογές που βασίζονται στο συγχρονισμό ενδέχεται να μην ενημερώνονται έως ότου τις ανοίξετε.\n\nΗ Εξοικονόμηση μπαταρίας απενεργοποιείται αυτόματα όταν η συσκευή σας φορτίζει."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Αποκλεισμένες: Να μην εμφανίζονται ποτέ αυτές οι ειδοποιήσεις"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Χαμηλής βαρύτητας: Να εμφανίζονται στο κάτω τμήμα της λίστας ειδοποιήσεων χωρίς τη συνοδεία ήχου"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Κανονική βαρύτητα: Να εμφανίζονται αυτές οι ειδοποιήσεις χωρίς ήχο"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one">Επιλέχτηκε <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Διάφορα"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 6c20763..9350ef7 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Deleted by your administrator"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"To help improve battery life, battery saver reduces your device’s performance and limits vibration, location services and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Importance"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blocked: Never show these notifications"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Low: Silently show at the bottom of the notification list"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: Silently show these notifications"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Miscellaneous"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"You set the importance of these notifications."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 6c20763..9350ef7 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Deleted by your administrator"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"To help improve battery life, battery saver reduces your device’s performance and limits vibration, location services and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Importance"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blocked: Never show these notifications"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Low: Silently show at the bottom of the notification list"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: Silently show these notifications"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Miscellaneous"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"You set the importance of these notifications."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 6c20763..9350ef7 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Updated by your administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Deleted by your administrator"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"To help improve battery life, battery saver reduces your device’s performance and limits vibration, location services and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Importance"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blocked: Never show these notifications"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Low: Silently show at the bottom of the notification list"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: Silently show these notifications"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selected</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Miscellaneous"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"You set the importance of these notifications."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"This is important because of the people involved."</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 4e2029f..7369278 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado por el administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Lo eliminó el administrador."</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Para ayudar a mejorar la duración de la batería, el ahorro de batería reduce el rendimiento del dispositivo y limita la vibración, los servicios de ubicación y la mayoría de los datos en segundo plano. Es posible que el correo electrónico, la mensajería y otras aplicaciones que se basan en la sincronización no puedan actualizarse, a menos que los abras.\n\nEl ahorro de batería se desactiva de forma automática cuando el dispositivo se está cargando."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloqueada: no mostrar nunca estas notificaciones"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Baja: mostrar en la parte inferior de la lista de notificación sin emitir sonido"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: mostrar estas notificaciones de manera silenciosa"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento seleccionado</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Varios"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 4868f6b..420981b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado por tu administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado por tu administrador"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Para ayudar a mejorar la duración de la batería, la función de ahorro de energía reduce el rendimiento del dispositivo y limita la vibración, los servicios de ubicación y la mayor parte de la transmisión de datos en segundo plano. Es posible que las aplicaciones que se sincronizan, como las de correo y mensajes, no se actualicen a menos que las abras.\n\nLa función de ahorro de energía se desactiva automáticamente cuando el dispositivo se está cargando."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloqueada: no mostrar estas notificaciones"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Baja: mostrar en la parte inferior de la lista de notificaciones de forma silenciosa"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: mostrar estas notificaciones de forma silenciosa"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> seleccionado</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Varios"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 3bbdcdf..ffaa4df 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Värskendas administraator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Kustutas teie administraator"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Aku kestuse parandamiseks vähendab akusäästja teie seadme toimivust ning piirab vibratsiooni, asukohateenuseid ja suuremat osa taustaandmetest. E-posti, sõnumsidet ja muid sünkroonimisele tuginevaid rakendusi võidakse värskendada ainult siis, kui te need avate.\n\nAkusäästja lülitatakse seadme laadimise ajal automaatselt välja."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blokeeritud: ära kunagi näita neid märguandeid"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Madal: kuva vaikselt märguannete loendi allosas"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Tavaline: kuva need märguanded vaikselt"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> on valitud</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Mitmesugust"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 13c8720..d32a0818 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Administratzaileak eguneratu du"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratzaileak ezabatu du"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Bateriak gehiago iraun dezan, bateria-aurrezleak gailuaren funtzionamendua, dardara,  kokapen-zerbitzuak eta atzeko planoko datuen erabilera gehiena mugatzen ditu. Posta elektronikoa, mezuak eta sinkronizatzen diren gainerako zerbitzuak ez dira eguneratuko ireki ezean.\n\nGailua kargatzen ezarri orduko desaktibatzen da bateria-aurrezlea."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blokeatuta: ez erakutsi jakinarazpen hauek"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Txikia: erakutsi jakinarazpen hauek zerrendaren behealdean"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normala: erakutsi jakinarazpen hauek, baina soinurik egin gabe"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> hautatuta</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Askotarikoak"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 9cbb29b..cf6df8e 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -674,7 +674,7 @@
     <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"‏سیم کارت شما به‌طور دائم غیر فعال شده است. \nبرای داشتن سیم کارت دیگر با ارائه‎دهنده سرویس بی‎سیم خود تماس بگیرید."</string>
     <string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"آهنگ قبلی"</string>
     <string name="lockscreen_transport_next_description" msgid="573285210424377338">"آهنگ بعدی"</string>
-    <string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"توقف موقت"</string>
+    <string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"مکث"</string>
     <string name="lockscreen_transport_play_description" msgid="1901258823643886401">"پخش"</string>
     <string name="lockscreen_transport_stop_description" msgid="5907083260651210034">"توقف"</string>
     <string name="lockscreen_transport_rew_description" msgid="6944412838651990410">"عقب بردن"</string>
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"توسط سرپرست شما به‌روزرسانی شد"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"توسط سرپرستتان حذف شد"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"برای کمک به بهبود عمر باتری، بهینه‌سازی باتری عملکرد دستگاهتان را کاهش می‌دهد و لرزش، سرویس‌های مبتنی بر مکان، و دسترسی به اکثر داده‌ها در پس‌زمینه را محدود می‌کند. ایمیل، پیام‌رسانی و برنامه‌های دیگری که به همگام‌سازی وابسته‌اند، تا زمانی‌که آن‌ها را باز نکنید نمی‌توانند به‌روز شوند.\n\nبهینه‌سازی باتری به‌صورت خودکار در هنگام شارژ شدن دستگاه خاموش می‌شود."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"مسدود: هرگز این اعلان‌ها نشان داده نشود"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"پایین: بدون صدا در پایین فهرست اعلان نشان داده شود"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"عادی: این اعلان‌ها بدون صدا نشان داده شود"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other">‏<xliff:g id="COUNT_1">%1$d</xliff:g> انتخاب شد</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"متفرقه"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 34b5fad..eea796e 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Järjestelmänvalvojasi on päivittänyt paketin."</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Järjestelmänvalvoja on poistanut paketin."</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Jos haluat parantaa akun kestoa, virransäästö vähentää laitteesi suorituskykyä ja rajoittaa värinää, sijaintipalveluita ja useimpia taustatietoja. Sähköposti, viestit ja muut synkronointiin perustuvat sovellukset eivät välttämättä päivity, ellet avaa niitä.\n\nVirransäästö poistuu käytöstä automaattisesti, kun laitteesi latautuu."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Estetty: älä koskaan näytä näitä ilmoituksia."</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Matala: näytä nämä ilmoitukset huomaamattomasti luettelon alaosassa."</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Tavallinen: näytä nämä ilmoitukset huomaamattomasti."</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> valittu</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Muut"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 9dad4c0..3afdcc0 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Mis à jour par votre administrateur"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Supprimé par votre administrateur"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Pour améliorer l\'autonomie de la pile, la fonction d\'économie d\'énergie réduit les performances de votre appareil et limite la vibration, les services de localisation ainsi que la plupart des données en arrière-plan. Les applications Courriel, Messages et d\'autres qui reposent sur la synchronisation ne peuvent pas se mettre à jour, sauf si vous les ouvrez. \n\n L\'économiseur d\'énergie se désactive automatiquement lorsque votre appareil est en charge."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloquée : ne jamais afficher ces notifications"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Faible : afficher en mode silencieux au bas de la liste de notifications"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normale : afficher ces notifications en mode silencieux"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Divers"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index dc08738..7ea8283 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Mis à jour par votre administrateur"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Supprimé par votre administrateur"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Pour améliorer l\'autonomie de la batterie, l\'économiseur de batterie réduit les performances et désactive le vibreur, les services de localisation et la plupart des données en arrière-plan. Les messageries électroniques ou autres applications utilisant la synchronisation pourraient ne pas se mettre à jour, sauf si vous les ouvrez.\n\nL\'économiseur de batterie s\'éteint automatiquement lorsque l\'appareil est en charge."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloquée : ne jamais afficher ces notifications"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Faible : afficher en mode silencieux au bas de la liste de notifications"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normale : afficher ces notifications en mode silencieux"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Divers"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 02ee7b45..83ba790 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizado polo administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado polo administrador"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Para axudar a mellorar a duración da batería, a función aforro de batería reduce o rendemento do teu dispositivo e limita a vibración, os servizos de localización e a maioría dos datos en segundo plano. É posible que o correo electrónico, as mensaxes e outras aplicacións que dependen da sincronización non se actualicen a menos que os abras. \n\nA función aforro de batería desactívase automaticamente cando pos a cargar o teu dispositivo."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloqueada: non mostrar nunca estas notificacións"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Baixa: mostrar de forma silenciosa na parte inferior da lista de notificacións"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: mostrar estas notificacións de forma silenciosa"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one">Seleccionouse <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Varios"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index c1187df..bcb3321 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"તમારા વ્યવસ્થાપક દ્વારા અપડેટ થયેલ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"તમારા વ્યવસ્થાપક દ્વારા કાઢી નાખેલ"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"બૅટરી આવરદા વધુ સારી કરવામાં સહાય માટે, બૅટરી સેવર તમારા ઉપકરણના પ્રદર્શનને ઘટાડે છે અને વાઇબ્રેશન, સ્થાન સેવાઓ અને મોટાભાગના પૃષ્ઠભૂમિ ડેટાને સીમિત કરે છે. ઇમેઇલ, મેસેજિંગ અને અન્ય એપ્લિકેશનો જે સમન્વયન પર આધાર રાખે છે તે તમે તેમને ખોલશો નહીં ત્યાં સુધી અપડેટ થઈ શકતી નથી.\n\nજ્યારે તમારું ઉપકરણ ચાર્જ થઈ રહ્યું હોય ત્યારે બૅટરી સેવર આપમેળે બંધ થઈ જાય છે."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"મહત્વ"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"અવરોધિત: આ સૂચનાઓ ક્યારેય બતાવશો નહીં"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"નિમ્ન: સૂચનાની સૂચિની નીચે ચુપચાપ બતાવો"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"સામાન્ય: આ સૂચનાઓ ચુપચાપ બતાવો"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> પસંદ કરી</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"વિવિધ"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"તમે આ સૂચનાઓનું મહત્વ સેટ કર્યું છે."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"શામેલ થયેલ લોકોને કારણે આ મહત્વપૂર્ણ છે."</string>
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index e81872a..ef8be64 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"आपके नियंत्रक द्वारा अपडेट किया गया"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"आपके नियंत्रक द्वारा हटाया गया"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"बैटरी जीवन काल को बेहतर बनाने में सहायता के लिए, बैटरी सेवर आपके डिवाइस के प्रदर्शन को कम कर देता है और कंपन, स्‍थान सेवाओं और अधिकांश पृष्‍ठभूमि डेटा को सीमित कर देता है. हो सकता है कि ईमेल, संदेश सेवा तथा समन्‍वयन पर आधारित अन्‍य ऐप्‍स तब तक ना खुलें जब तक कि आप उन्‍हें नहीं खोलते.\n\nजब आपका डिवाइस चार्ज हो रहा होता है तो बैटरी सेवर अपने आप बंद हो जाता है."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"महत्‍व"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"अवरोधित: ये नोटिफिकेशन कभी ना दिखाएं"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"निम्‍न: नोटिफिकेशन सूची के नीचे मौन रूप से दिखाएं"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"सामान्‍य: ये नोटिफिकेशन मौन रूप से दिखाएं"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> चयनित</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"विविध"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"आपने इन नोटिफिकेशन का महत्व सेट किया है."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"यह मौजूद व्यक्तियों के कारण महत्वपूर्ण है."</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index f53625e..0609843 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1310,7 +1310,7 @@
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Ukloni"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Želite li pojačati zvuk iznad preporučene razine?\n\nDugotrajno slušanje glasne glazbe može vam oštetiti sluh."</string>
     <string name="continue_to_enable_accessibility" msgid="1626427372316070258">"Nastavite držati s dva prsta kako biste omogućili pristupačnost."</string>
-    <string name="accessibility_enabled" msgid="1381972048564547685">"Dostupnost je omogućena."</string>
+    <string name="accessibility_enabled" msgid="1381972048564547685">"Pristupačnost je omogućena."</string>
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Pristupačnost otkazana."</string>
     <string name="user_switched" msgid="3768006783166984410">"Trenutačni korisnik <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="user_switching_message" msgid="2871009331809089783">"Prebacivanje na korisnika <xliff:g id="NAME">%1$s</xliff:g>…"</string>
@@ -1449,6 +1449,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ažurira vaš administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Izbrisao administrator"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Da bi se produljilo trajanje baterije, ušteda baterije smanjuje rad uređaja i ograničava vibraciju, usluge lokacije i većinu pozadinskih podataka. Aplikacije za e-poštu, slanje poruka i druge aplikacije koje se oslanjaju na sinkronizaciju možda se neće ažurirati ako ih ne otvorite.\n\nUšteda baterije isključuje se automatski dok se uređaj puni."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blokirano: nikad ne prikazuj te obavijesti"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Nisko: tiho prikaži na dnu popisa obavijesti"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Uobičajeno: prikazuj te obavijesti tiho"</string>
@@ -1528,4 +1530,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> odabranih</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Razno"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 2bb8fb0..0f3b849 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Frissítette a rendszergazda"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"A rendszergazda törölte"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Az akkumulátoridő növelése érdekében az energiatakarékos mód csökkenti az eszköz teljesítményét, és korlátozza a rezgést, a helyszolgáltatásokat, valamint a legtöbb háttéradatot is. Előfordulhat, hogy azok az e-mail-, üzenetküldő és egyéb alkalmazások, amelyek szinkronizálására számít, csak akkor frissítenek, ha megnyitja azokat.\n\nAz energiatakarékos mód automatikusan kikapcsol, ha eszköze töltőn van."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Fontosság"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Letiltva: soha nem jelennek meg ezek az értesítések"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Alacsony: az értesítések az értesítési lista végén jelennek meg hangjelzés nélkül"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normál: hang nélkül jelennek meg ezek az értesítések"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> kiválasztva</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Vegyes"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Ön állította be ezen értesítések fontossági szintjét."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"Ez az üzenet a résztvevők miatt fontos."</string>
 </resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 257d435..3fbdeb9 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ադմինիստրատորը թարմացրել է այն"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Ադմինիստրատորը ջնջել է այն"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Մարտկոցի աշխատանքի ժամկետը երկարացնելու նպատակով, մարտկոցի էներգիայի խնայման գործառույթը սահմանափակում է սարքի աշխատանքը, թրթռոցը, տեղադրության ծառայությունները և հետնաշերտում աշխատող շատ գործընթացներ: Էլփոստը, հաղորդագրությունների փոխանակումը և տվյալների համաժամեցումից կախված այլ հավելվածները կարող են չթարմացվել, եթե դուք դրանք չգործարկեք:\n\nԵրբ ձեր սարքը լիցքավորվում է, մարտկոցի էներգիայի խնայման գործառույթն ինքնաշխատորեն անջատվում է:"</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Արգելափակված է. Երբեք չցուցադրել այս ծանուցումները"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Ցածր. Ցուցադրել ծանուցումների ցանկի ներքևում առանց ձայնային ազդանշանի"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Նորմալ. Ցուցադրել այս ծանուցումներն առանց ձայնային ազդանշանի"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other">Ընտրված է՝ <xliff:g id="COUNT_1">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Զանազան"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 6be50d5..d13168a 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Diperbarui oleh administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Dihapus oleh administrator"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Untuk membantu meningkatkan masa pakai baterai, penghemat baterai mengurangi kinerja perangkat dan membatasi getaran, layanan lokasi, dan kebanyakan data latar belakang. Email, perpesanan, dan aplikasi lain yang mengandalkan sinkronisasi mungkin tidak diperbarui kecuali jika dibuka.\n\nPenghemat baterai otomatis nonaktif jika perangkat diisi dayanya."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Tingkat Kepentingan"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Diblokir: Jangan pernah menampilkan notifikasi ini"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Rendah: Menampilkan di bagian bawah daftar notifikasi secara diam-diam"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: Menampilkan notifikasi ini secara diam-diam"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dipilih</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Lain-Lain"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Anda menyetel tingkat kepentingan notifikasi ini."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"Ini penting karena orang-orang yang terlibat."</string>
 </resources>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index c2b8a8c..b362bef 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Uppfært af kerfisstjóranum"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Eytt af kerfisstjóra"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Til að auka endingu rafhlöðunnar mun orkusparnaður draga úr afköstum tækisins og takmarka titring, staðsetningarþjónustu og megnið af bakgrunnsgögnum. Ekki er víst að tölvupóstur, skilaboð og önnur forrit sem reiða sig á samstillingu uppfærist nema þú opnir þau.\n\nSjálfkrafa er slökkt á orkusparnaði þegar tækið er í hleðslu."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Útilokaðar: Aldrei sýna þessar tilkynningar"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Léttvægar: Sýna neðst á tilkynningalistanum án hljóðs"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Venjulegar: Sýna þessar tilkynningar án hljóðs"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valin</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Ýmislegt"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index c4614fc..66e7a2a 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Aggiornato dall\'amministratore"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminato dall\'amministratore"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Per aumentare la durata della batteria, la funzione di risparmio energetico riduce le prestazioni del dispositivo e limita vibrazione, servizi di localizzazione e la maggior parte dei dati in background. App di email, messaggi e altre app che si basano sulla sincronizzazione potrebbero essere aggiornate soltanto all\'apertura.\n\nLa funzione di risparmio energetico viene disattivata automaticamente quando il dispositivo è in carica."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloccato: non mostrare mai queste notifiche"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Bassa: mostra silenziosamente alla fine dell\'elenco di notifiche"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normale: mostra silenziosamente queste notifiche"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento selezionato</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Vari"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index f615187..b0c7437 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1458,6 +1458,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"עודכן על ידי מנהל המערכת שלך"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"נמחקה על ידי מנהל המערכת שלך"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"כדי לעזור בשיפור חיי הסוללה, תכונת החיסכון בסוללה מצמצמת את פעולות המכשיר ומגבילה רטט, שירותי מיקום ואת רוב נתוני הרקע. אימייל, העברת הודעות ואפליקציות אחרות המסתמכות על סנכרון עשויות שלא להתעדכן, אלא אם תפתח אותן.\n\nתכונת החיסכון בסוללה מושבתת אוטומטית כשהמכשיר בטעינה."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"חשיבות"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"חסימה: לעולם אל תציג הודעות אלה"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"נמוכה: הצג בתחתית רשימת ההודעות בלי להשמיע צליל"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"רגילה: הצג הודעות אלה בלי להשמיע צליל"</string>
@@ -1546,4 +1547,6 @@
       <item quantity="one">בחרת <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"שונות"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"אתה מגדיר את חשיבותן של הודעות אלה."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"ההודעה חשובה בשל האנשים המעורבים."</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 6dd4e9a..6b3e278 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"管理者によって更新されています"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"管理者によって削除されました"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限します。メール、SMSや、同期を使用するその他のアプリは、起動しても更新されないことがあります。\n\nバッテリーセーバーは端末の充電中は自動的にOFFになります。"</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"ブロック: 今後はこの通知を表示しない"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"低: 通知リストの下にマナーモードで表示する"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"標準: この通知をマナーモードで表示する"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g>件選択済み</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"その他"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 6709d92..38b2062 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"განახლებულია თქვენი ადმინისტრატორის მიერ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"თქვენი ადმინისტრატორის მიერ წაშლილი"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"ელემენტის მოქმედების ვადის გაუმჯობესებისათვის, ელემენტის დამზოგი ამცირებს თქვენი მოწყობილობის შესრულებას და ზღუდავს ვიბრაციას, ადგილმდებარეობის მომსახურებებს და ძირითად ფონურ მონაცემებს. ელ-ფოსტა, შეტყობინებები და სხვა სინქრონიზაციაზე დაყრდნობილი აპლიკაციების განახლება არ მოხდება მათ გახსნეამდე. \n\n ელემენტის დამზოგველი ავტომატურად გამოირთვება, როდესაც თქვენს მოწყობილობას დამტენთან შეაერთებთ."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"დაბლოკილი: ეს შეტყობინებები აღარასოდეს გამოჩნდება"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"დაბალი: ეს შეტყობინებები სიის ბოლოში, უხმოდ გამოჩნდება"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"ნორმალური: ეს შეტყობინებები უხმოდ გამოჩნდება"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> შერჩეული</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"სხვადასხვა"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 8d12034..6e26292 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Әкімші жаңартты"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Әкімші жойған"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Батареяның қызмет көрсету мерзімін жақсарту үшін батарея үнемдегіш құрылғының өнімділігін төмендетеді және дірілді, орынды анықтау қызметтерін және фондық деректердің көпшілігін шектейді. Электрондық пошта, хабар алмасу және синхрондауға негізделген басқа қолданбалар ашқанша жаңартылмауы мүмкін.\n\nБатарея үнемдегіш құрылғы зарядталып жатқанда автоматты түрде өшеді."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Маңыздылық"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Бұғатталған: осы хабарландыруларды ешқашан көрсетпеу"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Төмен: хабарландырулар тізімнің төменгі жағында үнсіз көрсету"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Қалыпты: осы хабарландыруларды үнсіз көрсету"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> таңдалды</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Әр түрлі"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Сіз осы хабарландырулардың маңыздылығын орнатасасыз."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"Қатысты адамдарға байланысты бұл маңызды."</string>
 </resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index dcaf305..167fa17 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1442,6 +1442,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"បានធ្វើបច្ចុប្បន្នភាពដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"បានលុបដោយអ្នកគ្រប់គ្រងរបស់អ្នក"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"ដើម្បីជួយឲ្យថាមពលថ្មប្រសើរឡើង កម្មវិធីសន្សំសំចៃថាមពលថ្មកាត់បន្ថយប្រតិបត្តិការឧបករណ៍របស់អ្នក និងកម្រិតភាពញ័រ សេវាកម្មទីតាំង និងទិន្នន័យផ្ទៃខាងក្រោយស្ទើរតែទាំងអស់។ ការផ្ញើសារអ៊ីម៉ែល និងកម្មវិធីផ្សេងទៀតដែលពឹងផ្អែកលើការធ្វើសមកាលកម្មអាចនឹងមិនធ្វើបច្ចុប្បន្នភាពទេ លុះត្រាតែអ្នកបើកពួកវា។\n\nកម្មវិធីសន្សំសំចៃបិទដោយស្វ័យប្រវត្តិ នៅពេលដែលឧបករណ៍របស់អ្នកកំពុងសាកថ្ម។"</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"សារៈសំខាន់"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"បានរារាំង៖ កុំបង្ហាញការជូនដំណឹងទាំងនេះ"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"កម្រិតទាប៖ បង្ហាញស្ងាត់ៗនៅផ្នែកខាងក្រោមបញ្ជីនៃការជូនដំណឹង"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"ធម្មតា៖ បង្ហាញការជូនដំណឹងទាំងនេះស្ងាត់ៗ"</string>
@@ -1512,4 +1513,6 @@
       <item quantity="one">បានជ្រើស <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"ផ្សេងៗ"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"អ្នកបានកំណត់សារៈសំខាន់នៃការជូនដំណឹងទាំងនេះ"</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"វាមានសារៈសំខាន់ដោយសារតែមនុស្សដែលពាក់ព័ន្ធ"</string>
 </resources>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index e7ad010..0ada13af 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ನವೀಕರಿಸಲಾಗಿದೆ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ಅಳಿಸಲಾಗಿದೆ"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"ನಿಮ್ಮ ಬ್ಯಾಟರಿಯ ಬಾಳಿಕೆಯನ್ನು ಸುಧಾರಿಸಲು ಸಹಾಯ ಮಾಡಲು, ಬ್ಯಾಟರಿ ಉಳಿಕೆಯು ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ವೈಬ್ರೇಷನ್, ಸ್ಥಳ ಸೇವೆಗಳು ಹಾಗೂ ಹೆಚ್ಚಿನ ಹಿನ್ನೆಲೆ ಡೇಟಾವನ್ನು ಮಿತಿಗೊಳಿಸುತ್ತದೆ. ಸಿಂಕ್ ಮಾಡುವುದನ್ನು ಅವಲಂಬಿಸಿರುವ ಇಮೇಲ್, ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ, ಮತ್ತು ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ನೀವು ತೆರೆಯದ ಹೊರತು ನವೀಕರಣಗೊಳ್ಳುವುದಿಲ್ಲ.\n\nನಿಮ್ಮ ಸಾಧನವು ಚಾರ್ಜ್ ಆಗುತ್ತಿರುವ ಸಮಯದಲ್ಲಿ ಬ್ಯಾಟರಿ ಉಳಿಕೆಯು ಆಫ್ ಆಗುತ್ತದೆ."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ: ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಎಂದಿಗೂ ತೋರಿಸಬೇಡ"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"ಕಡಿಮೆ: ಅಧಿಸೂಚನೆ ಪಟ್ಟಿಯ ಕೆಳಭಾಗದಲ್ಲಿ ಸ್ಥಬ್ಧವಾಗಿ ತೋರಿಸು"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"ಸಾಮಾನ್ಯ: ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಸ್ಥಬ್ಧವಾಗಿ ತೋರಿಸು"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"ಇತರೆ"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 85f46d1..e15df94 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"관리자에 의해 업데이트됨"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"관리자가 삭제함"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"배터리 수명 개선을 위해, 배터리 세이버는 기기의 성능을 줄이고 진동, 위치 서비스 및 대부분의 백그라운드 데이터를 제한합니다. 이메일, 메시지 및 동기화에 의존하는 기타 앱은 앱을 열 때까지 업데이트되지 않을 수 있습니다.\n\n배터리 세이버는 기기를 충전 중일 때는 자동으로 사용 중지됩니다."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"차단: 알림 다시 표시 안함"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"낮음: 알림 목록 하단에 무음으로 표시"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"일반: 무음으로 알림 표시"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g>개 선택됨</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"기타"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index bb1cd7f..af81c88 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1441,9 +1441,11 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Администраторуңуз жаңырткан"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Администраторуңуз тарабынан жок кылынган"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Батареянын өмүрүн узартуу үчүн, батареяны үнөмдөгүч түзмөгүңүздүн ишинин майнаптуулугун азайтып, дирилдөө, жайгашкан жерди аныктоо кызматтары жана фондук дайындардын көпчүлүгүн чектеп коёт. Электрондук почта, билдирүү жазышуу жана башка шайкештештирүүгө байланыштуу колдонмолор ачылмайынча жаңыртылбай калышы мүмкүн.\n\nБатарея үнөмдөгүч түзмөгүңүз кубатталып жатканда автоматтык түрдө өчүп калат."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Бөгөттөлгөн: Бул эскертмелер эч качан көрсөтүлбөсүн"</string>
-    <string name="notification_importance_low" msgid="6447640449918427187">"Төмөн: Эскертмелер тизмесинин эң ылдыйында көрсөтүлсүн"</string>
-    <string name="notification_importance_default" msgid="7991157697609575271">"Кадимки: Бул эскертмелер акырын көрсөтүлсүн"</string>
+    <string name="notification_importance_low" msgid="6447640449918427187">"Төмөн: Эскертмелер тизмесинин эң ылдыйында үнсүз көрсөтүлсүн"</string>
+    <string name="notification_importance_default" msgid="7991157697609575271">"Кадимки: Бул эскертмелер үнсүз көрсөтүлсүн"</string>
     <string name="notification_importance_high" msgid="3152238637737215654">"Жогору: Эскертмелер тизмесинин эң жогорусунда үн чыгарып көрсөтүлсүн"</string>
     <string name="notification_importance_max" msgid="1153693080467904474">"Шашылыш: Үн менен коштолуп, экранга чыгарылсын"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
@@ -1511,4 +1513,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> тандалды</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Калган-каткандар"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index bc58ea6..723a28a 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ອັບ​ເດດ​ໂດຍ​ຜູ້​ຄວບ​ຄຸມ​ຂອງ​ທ່ານ​ແລ້ວ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"ຖືກ​ຜູ້​ຄວບ​ຄຸມ​ຂອງ​ທ່ານ​ລຶບ​ໄປ​ແລ້ວ"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"ເພື່ອ​ຊ່ວຍ​ເພີ່ມ​ອາ​ຍຸ​ແບັດ​ເຕີ​ຣີ, ຕົວ​ປະ​ຢັດ​ໄຟ​ແບັດ​ເຕີ​ຣີ​ຫຼຸດ​ປະ​ສິດ​ທິ​ພາບ​ການ​ເຮັດ​ວຽກ​ຂອງ​ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ​ລົງ ແລະ​ຈຳ​ກັດ​ການ​ສັ່ນ, ການ​ບໍ​ລິ​ການ​ຫາທີ່ຕັ້ງ, ແລະ​ຂໍ້​ມູນ​ພື້ນ​ຫຼັງ​ເກືອບ​ທັງ​ໝົດ. ອີ​ເມວ, ການ​ສົ່ງ​ຂໍ້​ຄວາມ, ແລະ​ແອັບອື່ນໆ​ທີ່ອາ​ໄສການ​ຊິງ​ຄ໌​ອາດ​ຈະ​ບໍ່​ອັບ​ເດດ ນອກ​ຈາກວ່າ​ທ່ານ​ເປີດ​ມັນ.\n\nຕົວ​ປະ​ຢັດ​ໄຟ​ແບັດ​ເຕີ​ຣີຈະ​ປິດ​ອັດ​ຕະ​ໂນ​ມັດ ເມື່ອ​ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ​ກຳ​ລັງ​ສາກຢູ່."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"ບລັອກແລ້ວ: ຢ່າສະແດງການແຈ້ງເຕືອນເຫຼົ່ານີ້"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"ຕໍ່າ: ສະແດງຢູ່ສ່ວນລຸ່ມຂອງລາຍການແຈ້ງເຕືອນແບບມີບໍ່ສຽງ"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"ປົກກະຕິ: ສະແດງການແຈ້ງເຕືອນເຫຼົ່ານີ້ແບບບໍ່ມີສຽງ"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ຖືກເລືອກ​ແລ້ວ</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"ອື່ນໆ"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index b148d2c..67eff63 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1458,6 +1458,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atnaujino administratorius"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Ištrynė administratorius"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Kad tausotų akumuliatoriaus energiją akumuliatoriaus tausojimo priemonė sumažina įrenginio veikimą ir apriboja vibravimą, vietovės paslaugas bei daugumą foninių duomenų. El. pašto, susirašinėjimo ir kitos programos, kurios veikia sinchronizavimo pagrindu, gali būti neatnaujintos, nebent jas atidarysite.\n\nAkumuliatoriaus tausojimo priemonė automatiškai išjungiama, kai įrenginys įkraunamas."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Svarba"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Užblokuota: niekada nerodyti šių pranešimų"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Maža: tyliai rodyti pranešimų sąrašo apačioje"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Įprasta: tyliai rodyti šiuos pranešimus"</string>
@@ -1546,4 +1547,6 @@
       <item quantity="other">Pasir. <xliff:g id="COUNT_1">%1$d</xliff:g> elem.</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Įvairūs"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Galite nustatyti šių pranešimų svarbą."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"Tai svarbu dėl susijusių žmonių."</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 892402b..8c87e00 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1449,6 +1449,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atjaunināja administrators"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Izdzēsa jūsu administrators"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Lai paildzinātu akumulatora darbību, akumulatora jaudas taupīšanas režīmā tiek samazināta ierīces veiktspēja un tiek ierobežota vibrācija, atrašanās vietu pakalpojumi un lielākā daļa fona datu. E-pasta, ziņojumapmaiņas un cita veida lietotnes, kuru darbības pamatā ir datu sinhronizācija, var netikt atjauninātas, ja tās neatverat.\n\nTiklīdz tiek sākta ierīces uzlāde, akumulatora jaudas taupīšanas režīms automātiski tiek izslēgts."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloķēts: nekad nerādīt šos paziņojumus"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Zemu: rādīt paziņojumu saraksta apakšdaļā bez skaņas signāla"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normāli: rādīt šos paziņojumus bez skaņas signāla"</string>
@@ -1528,4 +1530,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīti</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Dažādi"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 9cfa6cf..124d7d6 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1442,6 +1442,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ажурирано од администраторот"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Избришано од администраторот"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"За да ви помогне да ја подобрите трајноста на батеријата, штедачот на батеријата ја намалува изведбата на уредот и го ограничува вибрирањето, услугите за локација и повеќето податоци од заднина. Е-поштата, испраќањето пораки и другите апликации кои се потпираат на синхронизација можеби нема да се ажурираат доколку не ги отворите.\n\nШтедачот на батеријата автоматски се исклучува кога уредот се полни."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Блокирано: никогаш не покажувај ги овие известувања"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Ниско: покажувај ги тивко на дното на списокот со известувања"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Нормално: покажувај ги овие известувања тивко"</string>
@@ -1512,4 +1514,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> се избрани</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Разно"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 3a3ec41..842ee4a 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"നിങ്ങളുടെ അഡ്‌മിനിസ്‌ട്രേറ്റർ അപ്‌ഡേറ്റുചെയ്‌തു"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"നിങ്ങളുടെ അഡ്‌മിനിസ്‌ട്രേറ്റർ ഇല്ലാതാക്കി"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"ബാറ്ററി ആയുസ്സ് മെച്ചപ്പെടുത്താൻ സഹായിക്കുന്നതിന്, ബാറ്ററി സേവർ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനത്തെ കുറയ്‌ക്കുകയും വൈബ്രേഷനെയും മിക്ക പശ്ചാത്തല വിവരത്തെയും പരിമിതപ്പെടുത്തുകയും ചെയ്യുന്നു. ഇമെയിൽ, സന്ദേശമയയ്‌ക്കൽ, സമന്വയിപ്പിക്കലിനെ ആശ്രയിച്ചുള്ള മറ്റ് അപ്ലിക്കേഷനുകൾ എന്നിവ നിങ്ങൾ തുറക്കുന്നതുവരെ അപ്‌ഡേറ്റുചെയ്യാനിടയില്ല.\n\nനിങ്ങളുടെ ഉപകരണം ചാർജ്ജുചെയ്യുമ്പോൾ ബാറ്ററി സേവർ സ്വയം ഓഫാകും."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"പ്രാധാന്യം"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"ബ്ലോക്കുചെയ്തു: ഈ അറിയിപ്പുകൾ ഒരിക്കലും കാണിക്കരുത്"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"താഴ്ന്നത്: അറിയിപ്പ് ലിസ്റ്റിന്റെ താഴെ ശബ്ദമുണ്ടാക്കാതെ കാണിക്കുക"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"സാധാരണം: ഈ അറിയിപ്പുകൾ നിശബ്ദമായി കാണിക്കുക"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> തിരഞ്ഞെടുത്തു</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"പലവക"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"ഈ അറിയിപ്പുകളുടെ പ്രാധാന്യം നിങ്ങൾ സജ്ജീകരിച്ചു."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"ഉൾപ്പെട്ടിട്ടുള്ള ആളുകളെ കണക്കിലെടുക്കുമ്പോള്‍ ഇത് പ്രധാനപ്പെട്ടതാണ്‌."</string>
 </resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index ab2285b..d989270 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Танай админ шинэчилсэн"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Таны админ устгасан байна"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Батарей хадгалах функц нь таны төхөөрөмжийн цэнэгийг хадгалахын тулд гүйцэтгэлийг багасгаж, чичрэлтийг бууруулж, байршлын үйлчилгээнүүд болон бусад өгөгдлийн хэмжээг багасгадаг юм. И-мэйл, мессеж болон бусад синхрон хийдэг апликейшнүүд дараа дахин нээгдэх хүртлээ автоматаар шинэчлэлт хийхгүй.\n\nМөн батарей хадгалах функц нь таныг төхөөрөмжөө цэнэглэх үед автоматаар унтрах юм."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Блоклосон: Эдгээр мэдэгдлийг хэзээ ч харуулахгүй"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Бага: Мэдэгдлийг жагсаалтын доод хэсэгт дуугүй харуулах"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Ердийн: Эдгээр мэдэгдлийг дуугүй харуулах"</string>
@@ -1508,4 +1510,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> сонгосон</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Бусад"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 92f114a..c323b85 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"आपल्या प्रशासकाद्वारे अद्यतनित केले"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"आपल्या प्रशासकाद्वारे हटविले आहे"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"बॅटरीचे आयुष्य सुधारित करण्‍यात मदत करण्यासाठी, बॅटरी बचतकर्ता आपल्या डिव्हाइसचे कार्यप्रदर्शन कमी करतो आणि कंपन, स्थान सेवा आणि बराच पार्श्वभूमी डेटा मर्यादित करतो. संकालनावर अवलंबून असणारे ईमेल, संदेशन आणि इतर अ‍ॅप्स आपण उघडल्याशिवाय अद्यतनित होऊ शकत नाहीत.\n\nआपले डिव्हाइस चार्ज होत असते तेव्हा बॅटरी बचतकर्ता स्वयंचलितपणे बंद होतो."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"महत्त्व"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"अवरोधित केले: या सूचना कधीही दर्शवू नका"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"कमी: शांतपणे सूचना सूचीच्या तळाशी दर्शवा"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"सामान्य: या सूचना शांतपणे दर्शवा"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> निवडले</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"संकीर्ण"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"आपण या सूचनांचे महत्त्व सेट केले."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"सामील असलेल्या लोकांमुळे हे महत्वाचे आहे."</string>
 </resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index ab683fcb..1993819 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Dikemas kini oleh pentadbir anda"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Dipadamkan oleh pentadbir anda"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Untuk membantu memperbaik hayat bateri, penjimat bateri mengurangkan prestasi peranti anda dan mengehadkan getaran, perkhidmatan lokasi dan kebanyakan data latar belakang. E-mel, pemesejan dan apl lain yang bergantung kepada penyegerakan mungkin tidak mengemas kini, melainkan anda membuka apl itu.\n\nPenjimat bateri dimatikan secara automatik semasa peranti anda sedang dicas."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Disekat: Jangan sekali-kali tunjukkan pemberitahuan ini"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Rendah: Tunjukkan pada bahagian bawah senarai pemberitahuan secara senyap"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Biasa: Tunjukkan pemberitahuan ini secara senyap"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dipilih</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Pelbagai"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 8709c7c..e8178e3 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"သင့်စီမံခန့်ခွဲသူမှ အဆင့်မြှင့်ထားပါသည်။"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"သင့် အက်ဒမင်အား ဖျက်ပစ်ရန်"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"ဘက်ထရီသက်တမ်း ကြာရှည်ခံရန်၊ ဘက်ထရီအားထိန်းသည် သင့်ကိရိယာ၏ ဆောင်ရွက်ချက်ကို  လျှော့ပေးပြီး တုန်ခါမှု၊ တည်နေရာဝန်ဆောင်မှုများနှင့်၊ နောက်ခံဒေတာအများစုကို ကန့်သတ်ပေး၏။ စင့်လုပ်ပေးရလေ့ရှိသည့် အီးမေး၊ စာပို့ခြင်းနှင့်၊ အခြားအပလီကေးရှင်းများကို ၎င်းတို့အား သင် ဖွင့်မှသာ အဆင့်မြှင့်မွမ်းမံမည်ဖြစ်၏။ \n\n ကိရိယာအား အားသွင်းနေစဉ် ဘက်ထရီအားထိန်းအား အလိုအလျောက် ပိတ်ထားသည်။"</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"အရေးပါမှု"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"ပိတ်ဆို့ထား- ဤသတိပေးချက်များကို ဘယ်တော့မှ မပြပါနှင့်"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"နိမ့်- တိတ်ဆိတ်စွာ သတိပေးချက်များ၏ စာရင်း အောက်ပိုင်းမှာ ပြပါ"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"\'ပုံမှန်- ဤသတိပေးချက်များကို တိတ်ဆိတ်စွာ ပြပါ"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ရွေးချယ်ပြီးပါပြီ</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"အထွေထွေ"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"ဤအသိပေးချက်များ၏ အရေးပါမှုကိုသင်သတ်မှတ်ပြီးပါပြီ။"</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"ပါဝင်သည့်လူများကြောင့် အရေးပါပါသည်။"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index c966e38..0e0f400 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Oppdatert av administratoren"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Slettet av administratoren"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"For å forlenge batterilevetiden reduserer batterispareren ytelsen til enheten din og begrenser vibrering, posisjonstjenester og mesteparten av bakgrunnsdataene. E-post, sending av meldinger og andre apper som er avhengig av synkronisering, oppdateres kanskje ikke med mindre du åpner dem.\n\nBatterisparing slås av automatisk når enheten lader."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blokkert: Aldri vis disse varslene"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Lavt: Vis nederst i varsellisten uten lyd"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normalt: Vis disse varslene uten lyd"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> er valgt</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 931c880..ec13ebb 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1446,8 +1446,9 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"तपाईँको प्रशासकद्वारा अद्यावधिक गरिएको"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"तपाईँको प्रशासकद्वारा हटाइएको"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"ब्याट्रीको आयु सुधार्न, ब्याट्री संरक्षकले तपाईँको यन्त्रको कार्यसम्पादन घटाउँछ र भाइब्रेसन, स्थान सेवा र बहुसंख्यक पृष्ठभूमि डेटा सीमित गर्दछ। इमेल, सन्देश, र अन्य अनुप्रयोगहरू जुन सिङ्कमा भर पर्छन् अद्यावधिक नहुन सक्छन् जबसम्म तपाईँ तिनीहरूलाई खोल्नुहुन्न\n\n ब्याट्री संरक्षक स्वत: निस्कृय हुन्छ जब तपाईँको यन्त्र चार्ज हुँदै हुन्छ।"</string>
-    <string name="notification_importance_blocked" msgid="7118826900767047125">"रोकिएको: यी सूचनाहरू कहिल्यै नदेखाउनुहोस्"</string>
-    <string name="notification_importance_low" msgid="6447640449918427187">"कम: चुपचाप सूचना सूचीको फेदमा देखाउनुहोस्"</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"महत्त्व"</string>
+    <string name="notification_importance_blocked" msgid="7118826900767047125">"रोकिएका: यी सूचनाहरू कहिल्यै नदेखाउनुहोस्"</string>
+    <string name="notification_importance_low" msgid="6447640449918427187">"न्यून: चुपचाप सूचना सूचीको फेदमा देखाउनुहोस्"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"सामान्य: चुपचाप यी सूचनाहरू देखाउनुहोस्"</string>
     <string name="notification_importance_high" msgid="3152238637737215654">"उच्च: सूचना सूचीको शीर्षमा देखाउनुहोस् र आवाज निकाल्नुहोस्"</string>
     <string name="notification_importance_max" msgid="1153693080467904474">"जरुरी: स्क्रिनमा झलक्क हेर्नुहोस् र आवाज निकाल्नुहोस्"</string>
@@ -1516,4 +1517,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> चयन गरियो</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"विविध"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"तपाईंले यी सूचनाहरू महत्त्व सेट गर्नुहुन्छ।"</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"यसमा सङ्लग्न भएका मानिसहरूको कारणले गर्दा यो महत्वपूर्ण छ।"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index ee4f63a..d30d836 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Geüpdatet door je beheerder"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Verwijderd door je beheerder"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Accubesparing beperkt de prestaties van je apparaat, de trilstand, locatieservices en de meeste achtergrondgegevens om de gebruiksduur van de accu te verlengen.\n\nAccubesparing wordt automatisch uitgeschakeld terwijl je apparaat wordt opgeladen."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Belang"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Geblokkeerd: deze meldingen nooit weergeven"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Laag: zonder geluid onder aan de lijst met meldingen weergeven"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normaal: deze meldingen zonder geluid weergeven"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> geselecteerd</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diversen"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Je stelt het belang van deze meldingen in."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"Dit is belangrijk vanwege de betrokken mensen."</string>
 </resources>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index ddc7b73..5a3b11a 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਪਡੇਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"ਤੁਹਾਡੇ ਪ੍ਰਬੰਧਕ ਵੱਲੋਂ ਮਿਟਾਇਆ ਗਿਆ"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"ਬੈਟਰੀ ਸਮਰੱਥਾ ਨੂੰ ਬਿਹਤਰ ਸਹਾਇਤਾ ਕਰਨ ਲਈ, ਬੈਟਰੀ ਸੇਵਰ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਦਾ ਪ੍ਰਦਰਸ਼ਨ ਘਟਾਉਂਦਾ ਹੈ ਅਤੇ ਵਾਈਬ੍ਰੇਸ਼ਨ, ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸੇਵਾਵਾਂ ਅਤੇ ਜ਼ਿਆਦਾਤਰ ਪਿਛੋਕੜ ਡਾਟਾ ਨੂੰ ਸੀਮਿਤ ਕਰਦਾ ਹੈ। ਈਮੇਲ, ਮੈਸੇਜਿੰਗ ਅਤੇ ਹੋਰ ਐਪਸ, ਜੋ ਸਿੰਕਿੰਗ ਤੇ ਨਿਰਭਰ ਹਨ, ਉਹ ਉਦੋਂ ਤੱਕ ਅਪਡੇਟ ਨਹੀਂ ਕੀਤੇ ਜਾ ਸਕਦੇ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਉਹਨਾਂ ਨੂੰ ਖੋਲ੍ਹਦੇ ਨਹੀਂ।\n\nਬੈਟਰੀ ਸੇਵਰ ਆਟੋਮੈਟਿਕਲੀ ਬੰਦ ਹੁੰਦਾ ਹੈ ਜਦੋਂ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਚਾਰਜ ਹੋ ਰਹੀ ਹੁੰਦੀ ਹੈ।"</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"ਬਲੌਕ ਕੀਤਾ: ਇਹ ਸੂਚਨਾਵਾਂ ਕਦੇ ਨਾ ਵਿਖਾਓ"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"ਘੱਟ: ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਵਿਖਾਓ"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"ਸਧਾਰਨ: ਇਹ ਸੂਚਨਾਵਾਂ ਚੁੱਪਚਾਪ ਢੰਗ ਨਾਲ ਵਿਖਾਓ"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ਚੁਣਿਆ ਗਿਆ</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"ਵਿਵਿਧ"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 7430d54..f206d82 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1458,6 +1458,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Zaktualizowane przez administratora"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Usunięty przez administratora"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Aby wydłużyć czas pracy baterii, Oszczędzanie baterii ogranicza aktywność urządzenia, w tym wibracje, usługi lokalizacyjne i przetwarzanie większości danych w tle. Poczta, czat i inne synchronizowane aplikacje mogą nie aktualizować swojej zawartości, dopóki ich nie otworzysz.\n\nOszczędzanie baterii wyłącza się automatycznie podczas ładowania urządzenia."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Zablokowana: nigdy nie pokazuj tych powiadomień"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Niska: pokazuj na dole listy powiadomień bez sygnału dźwiękowego"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normalna: pokazuj te powiadomienia bez sygnału dźwiękowego"</string>
@@ -1546,4 +1548,8 @@
       <item quantity="one">Wybrano <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Inne"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index f787499..7e33baa 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Excluído pelo seu administrador"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Para ajudar a melhorar a duração da bateria, o economizador de bateria reduz o desempenho e os limites de vibração do dispositivo, os serviços de localização e a maioria dos dados de segundo plano. E-mail, mensagens e outros aplicativos que dependem de sincronização não podem ser atualizados, a não ser que você os abra.\n\nO economizador de bateria é desligado automaticamente quando o dispositivo está sendo carregado."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloqueada: nunca mostrar essas notificações"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Baixa: mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: mostrar essas notificações de forma silenciosa"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diversos"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 826771e..f2e9402 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Eliminado pelo administrador"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Para ajudar a melhorar a autonomia da bateria, a poupança de bateria reduz o desempenho do seu dispositivo e limita a vibração, os serviços de localização e a maioria dos dados em segundo plano. O email, as mensagens e outras aplicações que dependem da sincronização não podem ser atualizados exceto se os abrir.\n\nA poupança de bateria desliga-se automaticamente quando o dispositivo está a carregar."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Importância"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloqueado: nunca mostrar estas notificações"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Baixo: mostrar na parte inferior da lista de notificações sem som"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: mostrar estas notificações sem som"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selecionado</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diversos"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Definiu a importância destas notificações."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"É importante devido às pessoas envolvidas."</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index f787499..7e33baa 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Atualizado pelo administrador"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Excluído pelo seu administrador"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Para ajudar a melhorar a duração da bateria, o economizador de bateria reduz o desempenho e os limites de vibração do dispositivo, os serviços de localização e a maioria dos dados de segundo plano. E-mail, mensagens e outros aplicativos que dependem de sincronização não podem ser atualizados, a não ser que você os abra.\n\nO economizador de bateria é desligado automaticamente quando o dispositivo está sendo carregado."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloqueada: nunca mostrar essas notificações"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Baixa: mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: mostrar essas notificações de forma silenciosa"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diversos"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index f49d6a1..c716c74 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1449,6 +1449,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Actualizat de un administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Șters de administrator"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Pentru a îmbunătăți autonomia bateriei, funcția de economisire a energiei reduce performanțele dispozitivului și limitează vibrațiile, serviciile de localizare și majoritatea datelor de fundal. Este posibil ca e-mailurile, mesageria și alte aplicații care depind de sincronizare să nu se actualizeze dacă nu le deschideți.\n\nFuncția de economisire a energiei se dezactivează automat când dispozitivul se încarcă."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blocate: aceste notificări nu se afișează niciodată"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Redusă: se afișează în partea de jos a listei cu notificări fără a se emite un sunet"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normală: aceste notificări se afișează fără a se emite un sunet"</string>
@@ -1528,4 +1530,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selectat</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index cee24da..5a2dcd9 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1458,6 +1458,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Обновлено администратором"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Удалено администратором"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Чтобы продлить время работы устройства от батареи, в режиме энергосбережения снижается производительность, а также ограничивается использование вибрации, геолокации и фоновой передачи данных. Данные, требующие синхронизации, могут обновляться только когда вы откроете приложение.\n\nРежим энергосбережения автоматически отключается во время зарядки устройства."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Заблокировано: не показывать эти уведомления"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Низкая: показывать без звука в конце списка уведомлений"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Обычная: показывать уведомления без звука"</string>
@@ -1546,4 +1548,8 @@
       <item quantity="other">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Другое"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index c8a45eb1..8584f0d 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1442,6 +1442,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"ඔබගේ පරිපාලක විසින් යාවත්කාලීන කරන ලදී"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"ඔබගේ පරිපාලක විසින් මකන ලද"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"බැටරි ආයු කාලය වැඩිදියුණු කිරීමට උදවු කිරීමට, බැටරි සුරැකුම ඔබේ උපාංගයේ ක්‍රියාකාරීත්වය අඩුකරන අතර කම්පනය, පිහිටීම් සේවා, සහ බොහෝමයක් පසුබිම් දත්ත සීමා කරයි. ඔබ ඒවා විවෘත නොකරන්නේ නම් මිස ඊමේල්, පණිවිඩකරණය, සහ සමමුහුර්ත කිරීම මත රඳා පවතින වෙනත් යෙදුම් යාවත්කාලීන නොවිය හැකිය.\n\nඔබේ උපාංගය ආරෝපණය වන විට බැටරි සුරැකුම ස්වයංක්‍රියව අක්‍රිය වේ."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"අවහිර කළ: මෙම දැනුම්දීම් කිසිදා නොපෙන්වන්න"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"අඩු: දැනුම්දීම් ලැයිස්තුවෙහි පහළින්ම නිශ්ශබ්දව පෙන්වන්න"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"සාමාන්‍ය: නිශ්ශබ්දව මෙම දැනුම්දීම් පෙන්වන්න"</string>
@@ -1512,4 +1514,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ක් තෝරන ලදි</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"විවිධාකාර"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 242a844..d26dcc6 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1458,6 +1458,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Aktualizované správcom"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Odstránený správcom"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"S cieľom predĺžiť výdrž batérie zníži šetrič batérie výkonnosť zariadenia a obmedzí vibrácie, služby určovania polohy a dátové prenosy na pozadí. Pošta, čet a ďalšie aplikácie, ktoré sa spoliehajú na synchronizáciu, sa možno nebudú aktualizovať, dokiaľ ich neotvoríte.\n\nPri nabíjaní zariadenia sa šetrič batérie automaticky vypne."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Dôležitosť"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blokované: Tieto upozornenia nikdy nezobrazovať"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Nízke: Zobrazovať v dolnej časti zoznamu upozornení bez zvukového signálu"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normálne: Tieto upozornenia zobrazovať bez zvukového signálu"</string>
@@ -1546,4 +1547,6 @@
       <item quantity="one">Vybrané: <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Rôzne"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Nastavili ste dôležitosť týchto upozornení."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"Táto správa je dôležitá vzhľadom na osoby, ktorých sa to týka."</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 3f6769c..6746a9e 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1458,6 +1458,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Posodobil skrbnik"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Izbrisal skrbnik"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Varčevanje z energijo akumulatorja podaljša čas njegovega delovanja tako, da zmanjša zmogljivost delovanja naprave in omeji vibriranje, lokacijske storitve ter prenos večine podatkov v ozadju. Aplikacije za e-pošto, sporočanje in drugo, ki uporabljajo sinhroniziranje, se morda ne posodabljajo, razen če jih odprete.\n\nVarčevanje z energijo akumulatorja se samodejno izklopi med polnjenjem akumulatorja naprave."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blokirano: nikoli ne prikaži teh obvestil"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Manj pomembno: prikaži na dnu seznama obvestil brez zvoka"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Običajno: prikaži ta obvestila brez zvoka"</string>
@@ -1546,4 +1548,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> izbranih</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Razno"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index 2653c71..4b1a45c 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Përditësuar nga administratori"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"U fshi nga administratori yt"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Për të përmirësuar jetëgjatësinë e baterisë, opsioni i kursimit të baterisë ul rendimentin e pajisjes tënde si dhe kufizon dridhjet dhe shumicën e të dhënave në sfond. Mail-i, mesazhet dhe aplikacionet e tjera që sinkronizohen automatikisht mund të mos përditësohen pa i hapur.\n\nKursimi i baterisë çaktivizohet automatikisht kur pajisja vihet në ngarkim."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Të bllokuara: Mos i shfaq asnjëherë këto njoftime"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Të ulëta: Shfaqi në heshtje në fund të listës së njoftimeve"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normale: Shfaqi këto njoftime në heshtje"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> i zgjedhur</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Të ndryshme"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 069d717..d7801b1 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1449,6 +1449,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ажурирао је администратор"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Избрисао је ваш адмиистратор"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Да би продужила време трајања батерије, уштеда батерије смањује перформансе уређаја и ограничава вибрацију, услуге локације и већину позадинских података. Имејл, размена порука и друге апликације које се ослањају на синхронизацију можда неће да се ажурирају ако их не отворите.\n\nУштеда батерије се аутоматски искључује када се уређај пуни."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Блокирана: Ова обавештења се никада не приказују"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Ниска: Приказују се у дну листе обавештења без звука"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Уобичајена: Ова обавештења се приказују без звука"</string>
@@ -1528,4 +1530,8 @@
       <item quantity="other">Изабрано је <xliff:g id="COUNT_1">%1$d</xliff:g> ставки</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Разно"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 748257a..8986073 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Uppdaterat av administratören"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Paketet har raderats av administratören"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"I batterisparläget reduceras enhetens prestanda så att batteriet ska räcka längre och vibration, platstjänster samt den mesta användningen av bakgrundsdata begränsas. Det kan hända att appar för e-post, sms och annat som kräver synkronisering inte uppdateras förrän du öppnar dem.\n\nBatterisparläget inaktiveras automatiskt när enheten laddas."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Relevans"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Blockerad: Visa aldrig dessa aviseringar"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Låg: Visa längst ned i aviseringslistan – utan ljud"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: Visa aviseringarna – utan ljud"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> har valts</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Diverse"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Du anger hur viktiga aviseringarna är."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"Detta är viktigt på grund av personerna som deltar."</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index cdb86ae..f00ff44 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1442,6 +1442,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Kimesasiswa na msimamizi wako"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Kilifutwa na msimamizi wako"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Kusaidia kuboresha muda wa matumizi ya betri, inayookoa betri hupunguza utendaji wa kifaa chako na kupunguza mtetemo, huduma za utambuzi wa mahali, na data nyingi ya chini chini. Barua pepe, ujumbe na programu nyingine zinazotege,ea usawazishaji huenda zisisasishwe usipozifungua.\n\nInayookoa betri hujizima kiotomatiki kifaa chako kinapokuwa kinachaji."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Imezuiwa: Usionyeshe arifa hizi kamwe"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Chini: Onyesha katika sehemu ya chini ya orodha ya arifa bila kutoa sauti"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Kawaida: Onyesha arifa hizi bila sauti"</string>
@@ -1512,4 +1514,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> kimechaguliwa</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Anuwai"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 245f1ca..e419eea 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"உங்கள் நிர்வாகி புதுப்பித்துள்ளார்"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"நிர்வாகி நீக்கிவிட்டார்"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"பேட்டரி ஆயுளை மேம்படுத்த, பேட்டரி சேமிப்பான் உங்கள் சாதனத்தின் செயல்திறனைக் குறைத்து, அதிர்வு, இடச் சேவைகள் மற்றும் பெரும்பாலான பின்புலத் தரவு போன்றவற்றைக் கட்டுப்படுத்துகிறது. ஒத்திசைவைச் சார்ந்துள்ள மின்னஞ்சல், செய்தியிடல் மற்றும் பிற பயன்பாடுகள் திறக்கும்வரை, அவை புதுப்பிக்கப்படாமல் இருக்கலாம்.\n\nஉங்கள் ஃபோன் சார்ஜ் செய்யப்படும்போது, பேட்டரி சேமிப்பான் தானாகவே முடங்கும்."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"முக்கியத்துவம்"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"தடுக்கப்பட்டது: இந்த அறிவிப்புகளை ஒருபோதும் காட்டாது"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"குறைவு: ஒலியின்றி அறிவிப்புப் பட்டியலின் கீழே காட்டும்"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"இயல்பு: ஒலியின்றி இந்த அறிவிப்புகளைக் காட்டும்"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> தேர்ந்தெடுக்கப்பட்டது</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"இதர அமைப்பு"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"இந்த அறிவிப்புகளின் முக்கியத்துவத்தை அமைத்துள்ளீர்கள்."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"ஈடுபட்டுள்ளவர்களின் காரணமாக, இது முக்கியமானது."</string>
 </resources>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 1b63c2f..a6c80ad 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"మీ నిర్వాహకుడు నవీకరించారు"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"మీ నిర్వాహకులు తొలగించారు"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"బ్యాటరీ జీవితకాలాన్ని మెరుగుపరచడంలో సహాయపడటానికి, బ్యాటరీ సేవర్ మీ పరికరం పనితీరును తగ్గిస్తుంది మరియు వైబ్రేషన్‌ను, స్థాన సేవలను మరియు ఎక్కువ నేపథ్య డేటాను పరిమితం చేస్తుంది. ఇమెయిల్, మెసేజింగ్ మరియు సమకాలీకరణపై ఆధారపడే ఇతర అనువర్తనాలు మీరు వాటిని తెరిస్తే మినహా నవీకరించబడవు.\n\nమీ పరికరం ఛార్జ్ అవుతున్నప్పుడు బ్యాటరీ సేవర్ స్వయంచాలకంగా ఆఫ్ అవుతుంది."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"ప్రాముఖ్యత"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"బ్లాక్ చేయబడింది: ఈ నోటిఫికేషన్‌లను ఎప్పుడూ చూపదు"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"తక్కువ: నోటిఫికేషన్‌ల జాబితా దిగువ భాగంలో శబ్దం లేకుండా చూపుతుంది"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"సాధారణం: ఈ నోటిఫికేషన్‌లను శబ్దం లేకుండా చూపుతుంది"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ఎంచుకోబడింది</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"ఇతరాలు"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"మీరు ఈ నోటిఫికేషన్‌ల ప్రాముఖ్యతను సెట్ చేసారు."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"ఇందులో పేర్కొనబడిన వ్యక్తులను బట్టి ఇది చాలా ముఖ్యమైనది."</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 57b9598..3576093 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"อัปเดตโดยผู้ดูแลระบบ"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"ลบโดยผู้ดูแลระบบของคุณ"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"เพื่อช่วยปรับปรุงอายุการใช้งานแบตเตอรี่ โหมดประหยัดแบตเตอรี่จะลดการทำงานของอุปกรณ์และจำกัดการสั่น บริการตำแหน่ง และข้อมูลแบ็กกราวด์ส่วนใหญ่ สำหรับอีเมล การรับส่งข้อความ และแอปอื่นๆ ที่ใช้การซิงค์จะไม่อัปเดตหากคุณไม่เปิดขึ้นมา\n\nโหมดประหยัดแบตเตอรี่จะปิดโดยอัตโนมัติขณะชาร์จอุปกรณ์"</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"บล็อก: อย่าแสดงการแจ้งเตือนเหล่านี้"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"ต่ำ: แสดงที่ด้านล่างของรายการแจ้งเตือนโดยไม่ส่งเสียง"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"ปกติ: แสดงการแจ้งเตือนเหล่านี้โดยไม่ส่งเสียง"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one">เลือกไว้ <xliff:g id="COUNT_0">%1$d</xliff:g> รายการ</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"เบ็ดเตล็ด"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 8cca676..639d368 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Na-update ng iyong administrator"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Na-delete ng iyong administrator"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Upang matulungang pagbutihin ang tagal ng baterya, binabawasan ng pangtipid ng baterya ang pagganap ng iyong device at nililimitahan ang pag-vibrate, mga serbisyo ng lokasyon at karamihan sa data ng background. Maaaring hindi mag-update ang email, pagmemensahe at iba pang mga app na umaasa sa pagsi-sync maliban kung buksan mo ang mga iyon.\n\nAwtomatikong nag-o-off ang pangtipid ng baterya kapag nagcha-charge ang iyong device."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Naka-block: Huwag kailanman ipakita ang mga notification na ito"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Mababa: Tahimik na ipakita sa ibaba ng listahan ng mga notification"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: Tahimik na ipakita ang mga notification na ito"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ang napili</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Iba Pa"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 60eee12..fea3e74 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Yöneticiniz tarafından güncellendi"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Yöneticiniz tarafından silindi"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Pil tasarrufu özelliği, pil ömrünü iyileştirmeye yardımcı olmak için cihazın performansını düşürür, titreşimi, konum hizmetlerini ve arka plan verilerinin çoğunu sınırlar. Senkronizasyona dayalı olarak çalışan e-posta, mesajlaşma uygulamaları ve diğer uygulamalar, bunları açmadığınız sürece güncellenmeyebilir.\n\nCihazınız şarj olurken pil tasarrufu otomatik olarak kapatılır."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Engellendi: Bu bildirimleri hiçbir zaman gösterme"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Düşük: Bildirim listesinin altında sessizce göster"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Normal: Bu bildirimleri sessizce göster"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> öğe seçildi</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Çeşitli"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index adf6234..e38ec1d 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1458,6 +1458,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Оновлено адміністратором"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Видалив адміністратор"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Щоб подовжити час роботи акумулятора, функція заощадження заряду акумулятора знижує продуктивність пристрою, а також обмежує вібрацію, функції служб локації та передавання більшості фонових даних. Електронна пошта, чати й інші додатки, які синхронізуються, можуть не оновлюватися, доки ви їх не відкриєте.\n\nФункція заощадження заряду акумулятора автоматично вимикається під час заряджання пристрою."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Пріоритет"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Заблоковано: не показувати ці сповіщення"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Низький пріоритет: показувати ці сповіщення внизу списку без звукового сигналу"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Стандартний пріоритет: показувати ці сповіщення без звукового сигналу"</string>
@@ -1546,4 +1547,6 @@
       <item quantity="other">Вибрано <xliff:g id="COUNT_1">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Інше"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Ви вказуєте пріоритет цих сповіщень."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"Важливе з огляду на учасників."</string>
 </resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 54af31e..517ac2b 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"آپ کے منتظم نے اپ ڈيٹ کر دیا"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"آپ کے منتظم کی جانب سے حذف کر دیا گیا"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"بیٹری کی میعاد بہتر کرنے میں مدد کرنے کیلئے، بیٹری سیور آپ کے آلہ کی کارکردگی کم کر دیتی ہے اور وائبریشن، مقام کی سروسز اور پس منظر کا بیشتر ڈیٹا محدود کر دیتی ہے۔ ای میل، پیغام رسانی اور مطابقت پذیری پر منحصر دیگر ایپس ممکن ہے اس وقت تک اپ ڈیٹ نہ ہوں جب تک آپ انہیں نہ کھولیں۔\n\nآپ کا آلہ چارج ہوتے وقت بیٹری سیور خود بخود آف ہو جاتی ہے۔"</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"مسدود کردہ: یہ اطلاعات کبھی مت دکھائیں"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"پست: اطلاعات کی فہرست کے نیچے خاموشی سے دکھائیں"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"عام: خاموشی سے یہ اطلاعات دکھائیں"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> منتخب کردہ</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"متفرقات"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index c4701b6..667be14 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1440,10 +1440,12 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Administratoringiz tomonidan yangilandi"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratoringiz tomonidan o‘chirilgan"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Batareya quvvatini uzoqroq vaqtga yetkazish uchun quvvat tejash funksiyasi qurilmangiz unumdorligini kamaytiradi hamda uning tebranishi va orqa fonda internetdan foydalanishini cheklaydi. Sinxronlanishni talab qiladigan e-pochta, xabar almashinuv va boshqa ilovalar esa qachonki ularni ishga tushirganingizda yangilanadi.\n\nQurilma quvvat olayotganda quvvat tejash funksiyasi avtomatik tarzda o‘chadi."</string>
-    <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloklangan: bildirishnomalar hech qachon ko‘rsatilmasin"</string>
-    <string name="notification_importance_low" msgid="6447640449918427187">"Past: bildirishnomalar ro‘yxatining pastida ovozsiz ko‘rsatilsin"</string>
-    <string name="notification_importance_default" msgid="7991157697609575271">"Oddiy: bildirishnomalar ovozsiz ko‘rsatilsin"</string>
-    <string name="notification_importance_high" msgid="3152238637737215654">"Yuqori: bildirishnomalar ro‘yxatining yuqorisida ovoz bilan ko‘rsatilsin"</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
+    <string name="notification_importance_blocked" msgid="7118826900767047125">"Bloklangan: bu bildirishnomalar boshqa ko‘rsatilmasin"</string>
+    <string name="notification_importance_low" msgid="6447640449918427187">"Past: bildirishnomalar ro‘yxatining oxirida ovozsiz ko‘rsatilsin"</string>
+    <string name="notification_importance_default" msgid="7991157697609575271">"Oddiy: bu bildirishnomalar ovozsiz ko‘rsatilsin"</string>
+    <string name="notification_importance_high" msgid="3152238637737215654">"Yuqori: bildirishnomalar ro‘yxatining boshida ovoz bilan ko‘rsatilsin"</string>
     <string name="notification_importance_max" msgid="1153693080467904474">"Shoshilinch: barcha oynalar ustida signal ovozi bilan ko‘rsatilsin"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
       <item quantity="other">%1$d daqiqa (<xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g> gacha)</item>
@@ -1510,4 +1512,8 @@
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta tanlandi</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Boshqa belgilar"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 336f10a..49e14df 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Được cập nhật bởi quản trị viên của bạn"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Đã bị xóa bởi quản trị viên của bạn"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Để giúp tăng tuổi thọ pin, trình tiết kiệm pin sẽ giảm hiệu suất thiết bị của bạn và hạn chế rung, dịch vụ vị trí và hầu hết dữ liệu nền. Email, nhắn tin và các ứng dụng khác dựa trên đồng bộ hóa có thể không cập nhật nếu bạn không mở chúng.\n\nTrình tiết kiệm pin tự động tắt khi thiết bị của bạn đang sạc."</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"Mức độ quan trọng"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Đã chặn: Không bao giờ hiển thị các thông báo này"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Thấp: Hiển thị im lặng ở cuối danh sách thông báo"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Bình thường: Hiển thị im lặng các thông báo này"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one">Đã chọn <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Khác"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"Bạn đặt tầm quan trọng của các thông báo này."</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"Thông báo này quan trọng vì những người có liên quan."</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index d54eb1e..9492994 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"由您单位的管理员更新"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"已被管理员删除"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"为了延长电池的续航时间,节电助手会降低设备的性能,并限制振动、位置信息服务和大部分后台流量。对于电子邮件、聊天工具等依赖于同步功能的应用,可能要打开这类应用时才能收到新信息。\n\n节电助手会在设备充电时自动关闭。"</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"屏蔽:一律不显示这些通知"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"低:在通知列表底部显示,不发出提示音"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"一般:显示这些通知,但不发出提示音"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one">已选择 <xliff:g id="COUNT_0">%1$d</xliff:g> 项</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"其他"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index a583e37..0526580 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1440,6 +1440,7 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"已由您的管理員更新"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"已由管理員刪除"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"節約電池用量模式有助於延長電池壽命,但這會降低裝置效能,並限制震動、定位服務及大部分背景數據傳輸。除非您啟用,否則電郵、短訊及其他需要使用同步功能的應用程式均不會更新。\n\n當裝置充電時,節約電池用量模式會自動關閉。"</string>
+    <string name="notification_importance_title" msgid="7493989722610008700">"重要性"</string>
     <string name="notification_importance_blocked" msgid="7118826900767047125">"已封鎖:永不顯示這些通知"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"低:以靜音方式顯示在通知清單底部"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"一般:以靜音方式顯示這些通知"</string>
@@ -1510,4 +1511,6 @@
       <item quantity="one">已選取 <xliff:g id="COUNT_0">%1$d</xliff:g> 個項目</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"其他"</string>
+    <string name="importance_from_topic" msgid="3572280439880023233">"您可以為這些通知設定重要性。"</string>
+    <string name="importance_from_person" msgid="9160133597262938296">"列為重要的原因:涉及使用者。"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 0d360493..8a2d610 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"由您的管理員更新"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"已遭管理員刪除"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"節約耗電量模式會透過降低裝置效能、震動限制、定位服務限制和大多數背景資料運作限制等方式,延長電池續航力。此外,如果未開啟電子郵件、簡訊和其他需要使用同步功能的應用程式,系統將不會自動更新這些應用程式。\n\n當您為裝置充電時,節約耗電量模式會自動關閉。"</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"封鎖:一律不顯示這些通知"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"低:顯示在通知清單底部且不發出任何音效"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"一般:顯示這些通知且不發出任何音效"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="one">已選取 <xliff:g id="COUNT_0">%1$d</xliff:g> 個項目</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"其他"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index ac88851..650ad33 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1440,6 +1440,8 @@
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Ibuyekezwe ngumqondisi wakho"</string>
     <string name="package_deleted_device_owner" msgid="7650577387493101353">"Isuswe ngumlawuli wakho"</string>
     <string name="battery_saver_description" msgid="1960431123816253034">"Ukusiza ukuthuthukisa impilo yebhethri, isilondoloze sebhethri sehlisa ukusebenza kwedivayisi yakho futhi sikhawulele ukudlidliza, amasevisi wendawo, nedatha eningi yangasemuva. I-imeyili, imilayezo, nezinye izinhlelo zokusebenza ezincike ekuvumelaniseni zingahle zingabuyekezwa ngaphandle kokuthi uzivule.\n\nIsilondolozi sebhethri siyavaleka ngokuzenzakalelayo uma idivayisi yakho ishaja."</string>
+    <!-- no translation found for notification_importance_title (7493989722610008700) -->
+    <skip />
     <string name="notification_importance_blocked" msgid="7118826900767047125">"Okuvinjiwe: Ungalokothi ubonise lezi zaziso"</string>
     <string name="notification_importance_low" msgid="6447640449918427187">"Okuphansi: Bonisa ngokuthulile ngaphansi kohlu lwesaziso"</string>
     <string name="notification_importance_default" msgid="7991157697609575271">"Okujwayelekile: Bonisa ngokuthulile lezi zaziso"</string>
@@ -1510,4 +1512,8 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> okukhethiwe</item>
     </plurals>
     <string name="default_notification_topic_label" msgid="227586145791870829">"Okwahlukahlukene"</string>
+    <!-- no translation found for importance_from_topic (3572280439880023233) -->
+    <skip />
+    <!-- no translation found for importance_from_person (9160133597262938296) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 786554c..9f13565 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2791,6 +2791,56 @@
             <flag name="end" value="0x20" />
         </attr>
 
+        <attr name="pointerShape">
+            <!-- Null icon, pointer becomes invisible. -->
+            <enum name="none" value="0" />
+            <!-- The default icon of arrow pointer. -->
+            <enum name="arrow" value="1000" />
+            <!-- Pointer icon indicating context-menu will appear. -->
+            <enum name="context_menu" value="1001" />
+            <!-- Pointer icon of a hand with the index finger. -->
+            <enum name="hand" value="1002" />
+            <!-- Pointer icon indicating help. -->
+            <enum name="help" value="1003" />
+            <!-- Pointer icon indicating something is going on and waiting. -->
+            <enum name="wait" value="1004" />
+            <!-- Pointer icon for cell and grid. -->
+            <enum name="cell" value="1006" />
+            <!-- Pointer icon of crosshair, indicating to spot a location. -->
+            <enum name="crosshair" value="1007" />
+            <!-- Pointer icon of I-beam, usually for text. -->
+            <enum name="text" value="1008" />
+            <!-- Pointer icon of I-beam with 90-degree rotated, for vertical text. -->
+            <enum name="vertical_text" value="1009" />
+            <!-- Pointer icon of 'alias', indicating an alias of/shortcut to something is to be
+                 created. -->
+            <enum name="alias" value="1010" />
+            <!-- Pointer icon of 'copy', used for drag/drop. -->
+            <enum name="copy" value="1011" />
+            <!-- Pointer icon of 'no-drop', indicating the drop will not be accepted at the
+                 current location. -->
+            <enum name="no_drop" value="1012" />
+            <!-- Pointer icon of four-way arrows, indicating scrolling all direction. -->
+            <enum name="all_scroll" value="1013" />
+            <!-- Pointer icon of horizontal double arrow, indicating horizontal resize. -->
+            <enum name="horizontal_double_arrow" value="1014" />
+            <!-- Pointer icon of vertical double arrow, indicating vertical resize. -->
+            <enum name="vertical_double_arrow" value="1015" />
+            <!-- Pointer icon of diagonal double arrow, starting from top-right to bottom-left.
+                 Indicating freeform resize. -->
+            <enum name="top_right_diagonal_double_arrow" value="1016" />
+            <!-- Pointer icon of diagonal double arrow, starting from top-left to bottom-right.
+                 Indicating freeform resize. -->
+            <enum name="top_left_diagonal_double_arrow" value="1017" />
+            <!-- Pointer icon indicating zoom-in. -->
+            <enum name="zoom_in" value="1018" />
+            <!-- Pointer icon indicating zoom-out. -->
+            <enum name="zoom_out" value="1019" />
+            <!-- Pointer icon of a hand sign to grab something. -->
+            <enum name="grab" value="1020" />
+            <!-- Pointer icon of a hand sign while grabbing something. -->
+            <enum name="grabbing" value="1021" />
+        </attr>
     </declare-styleable>
 
     <!-- Attributes that can be assigned to a tag for a particular View. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e2b1dbb..bff8b1a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1018,6 +1018,10 @@
     <!-- Light sensor event rate in milliseconds for automatic brightness control. -->
     <integer name="config_autoBrightnessLightSensorRate">250</integer>
 
+    <!-- The maximum range of gamma adjustment possible using the screen
+         auto-brightness adjustment setting. -->
+    <fraction name="config_autoBrightnessAdjustmentMaxGamma">300%</fraction>
+
     <!-- If we allow automatic adjustment of screen brightness while dozing, how many times we want
          to reduce it to preserve the battery. Value of 100% means no scaling. -->
     <fraction name="config_screenAutoBrightnessDozeScaleFactor">100%</fraction>
@@ -1035,6 +1039,9 @@
          adapt to the environment.  This mode may be better suited for watches. -->
     <bool name="config_autoBrightnessResetAmbientLuxAfterWarmUp">true</bool>
 
+    <!-- Period of time in which to consider light samples in milliseconds. -->
+    <integer name="config_autoBrightnessAmbientLightHorizon">10000</integer>
+
     <!-- Screen brightness used to dim the screen when the user activity
          timeout expires.  May be less than the minimum allowed brightness setting
          that can be set by the user. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index addeb05..ad36f3c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2684,6 +2684,7 @@
     <public type="attr" name="preferenceFragmentStyle" />
     <public type="attr" name="canControlMagnification" />
     <public type="attr" name="languageTag" />
+    <public type="attr" name="pointerShape" />
 
     <public type="style" name="Theme.Material.DayNight" />
     <public type="style" name="Theme.Material.DayNight.DarkActionBar" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index bf758c2..36ba306 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1693,6 +1693,8 @@
   <java-symbol type="fraction" name="config_dimBehindFadeDuration" />
   <java-symbol type="fraction" name="config_displayFractionForDefaultMinimalSizeOfResizeableTask" />
   <java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
+  <java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" />
+  <java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/>
   <java-symbol type="integer" name="config_autoBrightnessBrighteningLightDebounce"/>
   <java-symbol type="integer" name="config_autoBrightnessDarkeningLightDebounce"/>
   <java-symbol type="integer" name="config_autoBrightnessLightSensorRate"/>
diff --git a/drm/java/android/drm/DrmInfo.java b/drm/java/android/drm/DrmInfo.java
index 22d06c7..8c43252 100644
--- a/drm/java/android/drm/DrmInfo.java
+++ b/drm/java/android/drm/DrmInfo.java
@@ -17,6 +17,7 @@
 package android.drm;
 
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 
@@ -52,7 +53,7 @@
         if (!isValid()) {
             final String msg = "infoType: " + infoType + "," +
                                "mimeType: " + mimeType + "," +
-                               "data: " + data;
+                               "data: " + Arrays.toString(data);
 
             throw new IllegalArgumentException(msg);
         }
@@ -79,7 +80,7 @@
         if (!isValid()) {
             final String msg = "infoType: " + infoType + "," +
                                "mimeType: " + mimeType + "," +
-                               "data: " + mData;
+                               "data: " + Arrays.toString(mData);
 
             throw new IllegalArgumentException();
         }
diff --git a/drm/java/android/drm/DrmRights.java b/drm/java/android/drm/DrmRights.java
index a9b4f05..8747f77 100644
--- a/drm/java/android/drm/DrmRights.java
+++ b/drm/java/android/drm/DrmRights.java
@@ -18,6 +18,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Arrays;
 
 /**
  * An entity class that wraps the license information retrieved from the online DRM server.
@@ -103,7 +104,7 @@
         mMimeType = mimeType;
         if (!isValid()) {
             final String msg = "mimeType: " + mMimeType + "," +
-                               "data: " + mData;
+                               "data: " + Arrays.toString(mData);
             throw new IllegalArgumentException(msg);
         }
     }
@@ -127,7 +128,7 @@
 
         if (!isValid()) {
             final String msg = "mimeType: " + mMimeType + "," +
-                               "data: " + mData;
+                               "data: " + Arrays.toString(mData);
             throw new IllegalArgumentException(msg);
         }
     }
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 6a1167a..529849e 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -439,6 +439,17 @@
     }
 }
 
+void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
+    AutoMutex _l(mLock);
+
+    const int32_t iconId = mPolicy->getCustomPointerIconId();
+    mLocked.additionalMouseResources[iconId] = icon;
+    mLocked.requestedPointerShape = iconId;
+    mLocked.presentationChanged = true;
+
+    updatePointerLocked();
+}
+
 void PointerController::handleMessage(const Message& message) {
     switch (message.what) {
     case MSG_INACTIVITY_TIMEOUT:
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 4fd2d85..9ba37b3 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -67,6 +67,7 @@
     virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
             std::map<int32_t, PointerAnimation>* outAnimationResources) = 0;
     virtual int32_t getDefaultPointerIconId() = 0;
+    virtual int32_t getCustomPointerIconId() = 0;
 };
 
 
@@ -105,6 +106,7 @@
     virtual void clearSpots();
 
     void updatePointerShape(int32_t iconId);
+    void setCustomPointerIcon(const SpriteIcon& icon);
     void setDisplayViewport(int32_t width, int32_t height, int32_t orientation);
     void setInactivityTimeout(InactivityTimeout inactivityTimeout);
     void reloadPointerResources();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
index b99c806..6d947d1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
@@ -28,6 +28,7 @@
 import android.content.ContentProviderClient;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.net.Uri;
@@ -170,8 +171,27 @@
 
             setupCopyJob(srcs, stack, transferMode);
 
+            final String opDesc = transferMode == TRANSFER_MODE_COPY ? "copy" : "move";
+            DocumentInfo srcInfo;
+            DocumentInfo dstInfo;
             for (int i = 0; i < srcs.size() && !mIsCancelled; ++i) {
-                copy(srcs.get(i), stack.peek(), transferMode);
+                srcInfo = srcs.get(i);
+                dstInfo = stack.peek();
+
+                // Guard unsupported recursive operation.
+                if (dstInfo.equals(srcInfo) || isDescendentOf(srcInfo, dstInfo)) {
+                    if (DEBUG) Log.d(TAG,
+                            "Skipping recursive " + opDesc + " of directory " + dstInfo.derivedUri);
+                    mFailedFiles.add(srcInfo);
+                    continue;
+                }
+
+                if (DEBUG) Log.d(TAG,
+                        "Performing " + opDesc + " of " + srcInfo.displayName
+                        + " (" + srcInfo.derivedUri + ")" + " to " + dstInfo.displayName
+                        + " (" + dstInfo.derivedUri + ")");
+
+                copy(srcInfo, dstInfo, transferMode);
             }
         } catch (Exception e) {
             // Catch-all to prevent any copy errors from wedging the app.
@@ -447,22 +467,6 @@
      */
     private void copy(DocumentInfo srcInfo, DocumentInfo dstDirInfo, int mode)
             throws RemoteException {
-
-        String opDesc = mode == TRANSFER_MODE_COPY ? "copy" : "move";
-
-        // Guard unsupported recursive operation.
-        if (dstDirInfo.equals(srcInfo) || isDescendentOf(srcInfo, dstDirInfo)) {
-            if (DEBUG) Log.d(TAG,
-                    "Skipping recursive " + opDesc + " of directory " + dstDirInfo.derivedUri);
-            mFailedFiles.add(srcInfo);
-            return;
-        }
-
-        if (DEBUG) Log.d(TAG,
-                "Performing " + opDesc + " of " + srcInfo.displayName
-                + " (" + srcInfo.derivedUri + ")" + " to " + dstDirInfo.displayName
-                + " (" + dstDirInfo.derivedUri + ")");
-
         // When copying within the same provider, try to use optimized copying and moving.
         // If not supported, then fallback to byte-by-byte copy/move.
         if (srcInfo.authority.equals(dstDirInfo.authority)) {
@@ -490,6 +494,8 @@
             }
         }
 
+        // Create the target document (either a file or a directory), then copy recursively the
+        // contents (bytes or children).
         final Uri dstUri = DocumentsContract.createDocument(mDstClient, dstDirInfo.derivedUri,
                 srcInfo.mimeType, srcInfo.displayName);
         if (dstUri == null) {
@@ -498,10 +504,30 @@
             return;
         }
 
-        if (srcInfo.isDirectory()) {
-            copyDirectoryHelper(srcInfo.derivedUri, dstUri, mode);
+        DocumentInfo dstInfo = null;
+        try {
+            final DocumentInfo dstDocInfo = DocumentInfo.fromUri(getContentResolver(), dstUri);
+        } catch (FileNotFoundException e) {
+            mFailedFiles.add(srcInfo);
+            return;
+        }
+
+        if (Document.MIME_TYPE_DIR.equals(srcInfo.mimeType)) {
+            copyDirectoryHelper(srcInfo, dstInfo, mode);
         } else {
-            copyFileHelper(srcInfo.derivedUri, dstUri, mode);
+            copyFileHelper(srcInfo, dstInfo, mode);
+        }
+
+        if (mode == TRANSFER_MODE_MOVE) {
+            try {
+                DocumentsContract.deleteDocument(mSrcClient, srcInfo.derivedUri);
+            } catch (RemoteException e) {
+                // RemoteExceptions usually signal that the connection is dead, so there's no
+                // point attempting to continue. Propagate the exception up so the copy job is
+                // cancelled.
+                Log.w(TAG, "Failed to clean up after move: " + srcInfo.derivedUri, e);
+                throw e;
+            }
         }
     }
 
@@ -520,48 +546,29 @@
      * Handles recursion into a directory and copying its contents. Note that in linux terms, this
      * does the equivalent of "cp src/* dst", not "cp -r src dst".
      *
-     * @param srcDirUri URI of the directory to copy from. The routine will copy the directory's
+     * @param srcDirInfo Info of the directory to copy from. The routine will copy the directory's
      *            contents, not the directory itself.
-     * @param dstDirUri URI of the directory to copy to. Must be created beforehand.
+     * @param dstDirInfo Info of the directory to copy to. Must be created beforehand.
      * @throws RemoteException
      */
-    private void copyDirectoryHelper(Uri srcDirUri, Uri dstDirUri, int mode)
+    private void copyDirectoryHelper(DocumentInfo srcDirInfo, DocumentInfo dstDirInfo, int mode)
             throws RemoteException {
         // Recurse into directories. Copy children into the new subdirectory.
         final String queryColumns[] = new String[] {
                 Document.COLUMN_DISPLAY_NAME,
                 Document.COLUMN_DOCUMENT_ID,
                 Document.COLUMN_MIME_TYPE,
-                Document.COLUMN_SIZE
+                Document.COLUMN_SIZE,
+                Document.COLUMN_FLAGS
         };
-        final Uri queryUri = DocumentsContract.buildChildDocumentsUri(srcDirUri.getAuthority(),
-                DocumentsContract.getDocumentId(srcDirUri));
         Cursor cursor = null;
         try {
             // Iterate over srcs in the directory; copy to the destination directory.
-            cursor = mSrcClient.query(queryUri, queryColumns, null, null, null);
+            DocumentInfo srcInfo;
+            cursor = mSrcClient.query(srcDirInfo.derivedUri, queryColumns, null, null, null);
             while (cursor.moveToNext()) {
-                final String childMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
-                final Uri dstUri = DocumentsContract.createDocument(mDstClient, dstDirUri,
-                        childMimeType, getCursorString(cursor, Document.COLUMN_DISPLAY_NAME));
-                final Uri childUri = DocumentsContract.buildDocumentUri(srcDirUri.getAuthority(),
-                        getCursorString(cursor, Document.COLUMN_DOCUMENT_ID));
-                if (Document.MIME_TYPE_DIR.equals(childMimeType)) {
-                    copyDirectoryHelper(childUri, dstUri, mode);
-                } else {
-                    copyFileHelper(childUri, dstUri, mode);
-                }
-            }
-            if (mode == TRANSFER_MODE_MOVE) {
-                try {
-                    DocumentsContract.deleteDocument(mSrcClient, srcDirUri);
-                } catch (RemoteException e) {
-                    // RemoteExceptions usually signal that the connection is dead, so there's no
-                    // point attempting to continue. Propagate the exception up so the copy job is
-                    // cancelled.
-                    Log.w(TAG, "Failed to clean up after move: " + srcDirUri, e);
-                    throw e;
-                }
+                srcInfo = DocumentInfo.fromCursor(cursor, srcDirInfo.authority);
+                copy(srcInfo, dstDirInfo, mode);
             }
         } finally {
             IoUtils.closeQuietly(cursor);
@@ -571,11 +578,11 @@
     /**
      * Handles copying a single file.
      *
-     * @param srcUri URI of the file to copy from.
-     * @param dstUri URI of the *file* to copy to. Must be created beforehand.
+     * @param srcUriInfo Info of the file to copy from.
+     * @param dstUriInfo Info of the *file* to copy to. Must be created beforehand.
      * @throws RemoteException
      */
-    private void copyFileHelper(Uri srcUri, Uri dstUri, int mode)
+    private void copyFileHelper(DocumentInfo srcInfo, DocumentInfo dstInfo, int mode)
             throws RemoteException {
         // Copy an individual file.
         CancellationSignal canceller = new CancellationSignal();
@@ -586,9 +593,26 @@
 
         IOException copyError = null;
         try {
-            srcFile = mSrcClient.openFile(srcUri, "r", canceller);
-            dstFile = mDstClient.openFile(dstUri, "w", canceller);
-            src = new ParcelFileDescriptor.AutoCloseInputStream(srcFile);
+            // If the file is virtual, but can be converted to another format, then try to copy it
+            // as such format.
+            if (srcInfo.isVirtualDocument() && srcInfo.isTypedDocument()) {
+                final String[] streamTypes = mSrcClient.getStreamTypes(srcInfo.derivedUri, "*/*");
+                if (streamTypes.length > 0) {
+                    // Pick the first streamable format.
+                    final AssetFileDescriptor srcFileAsAsset =
+                            mSrcClient.openTypedAssetFileDescriptor(
+                                    srcInfo.derivedUri, streamTypes[0], null, canceller);
+                    srcFile = srcFileAsAsset.getParcelFileDescriptor();
+                    src = new AssetFileDescriptor.AutoCloseInputStream(srcFileAsAsset);
+                } else {
+                    // TODO: Log failures. b/26192412
+                    mFailedFiles.add(srcInfo);
+                }
+            } else {
+                srcFile = mSrcClient.openFile(srcInfo.derivedUri, "r", canceller);
+                src = new ParcelFileDescriptor.AutoCloseInputStream(srcFile);
+            }
+            dstFile = mDstClient.openFile(dstInfo.derivedUri, "w", canceller);
             dst = new ParcelFileDescriptor.AutoCloseOutputStream(dstFile);
 
             byte[] buffer = new byte[8192];
@@ -601,18 +625,7 @@
             srcFile.checkError();
         } catch (IOException e) {
             copyError = e;
-
-            try {
-                DocumentInfo info = DocumentInfo.fromUri(getContentResolver(), srcUri);
-                mFailedFiles.add(info);
-            } catch (FileNotFoundException ignore) {
-                // Generate a dummy DocumentInfo so an error still gets reflected in the UI for this
-                // file.
-                DocumentInfo info = new DocumentInfo();
-                info.derivedUri = srcUri;
-                info.displayName = "Unknown [" + srcUri + "]";
-                mFailedFiles.add(info);
-            }
+            mFailedFiles.add(srcInfo);
 
             if (dstFile != null) {
                 try {
@@ -627,26 +640,17 @@
             IoUtils.closeQuietly(dst);
         }
 
-
         if (copyError != null || mIsCancelled) {
             // Clean up half-copied files.
             canceller.cancel();
             try {
-                DocumentsContract.deleteDocument(mDstClient, dstUri);
+                DocumentsContract.deleteDocument(mDstClient, dstInfo.derivedUri);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed to clean up after copy error: " + dstUri, e);
+                Log.w(TAG, "Failed to clean up after copy error: " + dstInfo.derivedUri, e);
                 // RemoteExceptions usually signal that the connection is dead, so there's no point
                 // attempting to continue. Propagate the exception up so the copy job is cancelled.
                 throw e;
             }
-        } else if (mode == TRANSFER_MODE_MOVE) {
-            // Clean up src files after a successful move.
-            try {
-                DocumentsContract.deleteDocument(mSrcClient, srcUri);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to clean up after move: " + srcUri, e);
-                throw e;
-            }
         }
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index bf44013..0b6a09f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -101,21 +101,24 @@
             // from EXTRA_STACK intent extra. In this case, we'll skip other means of
             // loading or restoring the stack.
             if (!mState.stack.isEmpty()) {
+                if (DEBUG) Log.d(TAG, "Launching with non-empty stack.");
                 // When restoring from a stack, if a URI is present, it should only ever
                 // be a launch URI. Launch URIs support sensible activity management, but
-                // don't specify an real content target.
-                if (uri != null) {
-                    checkState(LauncherActivity.isLaunchUri(uri));
-                }
+                // don't specify a real content target.
+                checkState(uri == null || LauncherActivity.isLaunchUri(uri));
                 onCurrentDirectoryChanged(ANIM_NONE);
             } else if (DocumentsContract.isRootUri(this, uri)) {
+                if (DEBUG) Log.d(TAG, "Launching with root URI.");
                 // If we've got a specific root to display, restore that root using a dedicated
                 // authority. That way a misbehaving provider won't result in an ANR.
                 new RestoreRootTask(uri).executeOnExecutor(
                         ProviderExecutor.forAuthority(uri.getAuthority()));
             } else {
-                // Finally, we try to restore a stack from recents.
-                new RestoreStackTask().execute();
+                if (DEBUG) Log.d(TAG, "Launching into Home directory.");
+                // If all else fails, try to load "Home" directory.
+                uri = DocumentsContract.buildHomeUri();
+                new RestoreRootTask(uri).executeOnExecutor(
+                        ProviderExecutor.forAuthority(uri.getAuthority()));
             }
 
             // TODO: Ensure we're handling CopyService errors correctly across all activities.
@@ -159,7 +162,17 @@
     @Override
     protected void onPostCreate(Bundle savedInstanceState) {
         super.onPostCreate(savedInstanceState);
-        updateActionBar();
+        // This check avoids a flicker from "Recents" to "Home".
+        // Only update action bar at this point if there is an active
+        // serach. Why? Because this avoid an early (undesired) load of
+        // the recents root...which is the default root in other activities.
+        // In Files app "Home" is the default, but it is loaded async.
+        // updateActionBar will be called once Home root is loaded.
+        // Except while searching we need this call to ensure the
+        // search bits get layed out correctly.
+        if (mSearchManager.isSearching()) {
+            updateActionBar();
+        }
     }
 
     @Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
index 69b574d..215c6e6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
@@ -251,6 +251,14 @@
         return isDirectory() || isArchive();
     }
 
+    public boolean isVirtualDocument() {
+        return (flags & Document.FLAG_VIRTUAL_DOCUMENT) != 0;
+    }
+
+    public boolean isTypedDocument() {
+        return (flags & Document.FLAG_SUPPORTS_TYPED_DOCUMENT) != 0;
+    }
+
     public int hashCode() {
         return derivedUri.hashCode() + mimeType.hashCode();
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index 71d8b34..f0dbfe9 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -137,11 +137,18 @@
         mBot.assertHasDocuments("file0.log", "file1.png", "file2.csv");
     }
 
+    public void testLoadsHomeByDefault() throws Exception {
+        initTestFiles();
+
+        mDevice.waitForIdle();
+        mBot.assertWindowTitle("Home");
+    }
+
     public void testRootClickSetsWindowTitle() throws Exception {
         initTestFiles();
 
-        mBot.openRoot("Home");
-        mBot.assertWindowTitle("Home");
+        mBot.openRoot("Downloads");
+        mBot.assertWindowTitle("Downloads");
     }
 
     public void testFilesList_LiveUpdate() throws Exception {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index 6fa0df2..1d72647 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
@@ -255,7 +255,7 @@
                 return;
             }
             if (mNumLoaded == 0) {
-                mDatabase.getMapper().startAddingChildDocuments(mIdentifier.mDocumentId);
+                mDatabase.getMapper().startAddingDocuments(mIdentifier.mDocumentId);
             }
             try {
                 mDatabase.getMapper().putChildDocuments(
@@ -266,7 +266,7 @@
                 mNumLoaded = 0;
             }
             if (getState() != STATE_LOADING) {
-                mDatabase.getMapper().stopAddingChildDocuments(mIdentifier.mDocumentId);
+                mDatabase.getMapper().stopAddingDocuments(mIdentifier.mDocumentId);
             }
         }
 
@@ -275,7 +275,7 @@
             mError = message;
             mNumLoaded = 0;
             if (lastState == STATE_LOADING) {
-                mDatabase.getMapper().stopAddingChildDocuments(mIdentifier.mDocumentId);
+                mDatabase.getMapper().stopAddingDocuments(mIdentifier.mDocumentId);
             }
         }
 
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
index 0d9d60c..322246a 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
@@ -18,6 +18,7 @@
 
 import static com.android.mtp.MtpDatabaseConstants.*;
 
+import android.annotation.Nullable;
 import android.content.ContentValues;
 import android.content.res.Resources;
 import android.database.Cursor;
@@ -36,17 +37,18 @@
 
 import static com.android.mtp.MtpDatabase.strings;
 
-
 /**
  * Mapping operations for MtpDatabase.
  * Also see the comments of {@link MtpDatabase}.
  */
 class Mapper {
+    private static final String[] EMPTY_ARGS = new String[0];
     private final MtpDatabase mDatabase;
 
     /**
-     * Mapping mode for roots/documents where we start adding child documents.
+     * Mapping mode for a parent. The key is document ID of parent, or null for root documents.
      * Methods operate the state needs to be synchronized.
+     * TODO: Replace this with unboxing int map.
      */
     private final Map<String, Integer> mMappingMode = new HashMap<>();
 
@@ -54,48 +56,43 @@
         mDatabase = database;
     }
 
-    /**
-     * Invokes {@link #startAddingDocuments} for root documents.
-     * @param deviceId Device ID.
-     */
-    synchronized void startAddingRootDocuments(int deviceId) {
-        final String mappingStateKey = getRootDocumentsMappingStateKey(deviceId);
-        Preconditions.checkState(!mMappingMode.containsKey(mappingStateKey));
-        mMappingMode.put(
-                mappingStateKey,
-                startAddingDocuments(
-                        SELECTION_ROOT_DOCUMENTS, Integer.toString(deviceId)));
-    }
-
-    /**
-     * Invokes {@link #startAddingDocuments} for child of specific documents.
-     * @param parentDocumentId Document ID for parent document.
-     */
-    @VisibleForTesting
-    synchronized void startAddingChildDocuments(String parentDocumentId) {
-        final String mappingStateKey = getChildDocumentsMappingStateKey(parentDocumentId);
-        Preconditions.checkState(!mMappingMode.containsKey(mappingStateKey));
-        mMappingMode.put(
-                mappingStateKey,
-                startAddingDocuments(SELECTION_CHILD_DOCUMENTS, parentDocumentId));
+    synchronized String putDeviceDocument(int deviceId, String name, MtpRoot[] roots) {
+        final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
+        Preconditions.checkState(mMappingMode.containsKey(/* no parent for root */ null));
+        database.beginTransaction();
+        try {
+            final ContentValues[] valuesList = new ContentValues[1];
+            valuesList[0] = new ContentValues();
+            MtpDatabase.getDeviceDocumentValues(valuesList[0], deviceId, name, roots);
+            putDocuments(
+                    valuesList,
+                    COLUMN_PARENT_DOCUMENT_ID + " IS NULL",
+                    EMPTY_ARGS,
+                    /* heuristic */ false,
+                    COLUMN_DEVICE_ID);
+            database.setTransactionSuccessful();
+            return valuesList[0].getAsString(Document.COLUMN_DOCUMENT_ID);
+        } finally {
+            database.endTransaction();
+        }
     }
 
     /**
      * Puts root information to database.
-     * @param deviceId Device ID
+     * @param parentDocumentId Document ID of device document.
      * @param resources Resources required to localize root name.
      * @param roots List of root information.
      * @return If roots are added or removed from the database.
      */
-    synchronized boolean putRootDocuments(int deviceId, Resources resources, MtpRoot[] roots) {
+    synchronized boolean putRootDocuments(
+            String parentDocumentId, Resources resources, MtpRoot[] roots) {
         final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
         database.beginTransaction();
         try {
             final boolean heuristic;
             final String mapColumn;
-            final String key = getRootDocumentsMappingStateKey(deviceId);
-            Preconditions.checkState(mMappingMode.containsKey(key));
-            switch (mMappingMode.get(key)) {
+            Preconditions.checkState(mMappingMode.containsKey(parentDocumentId));
+            switch (mMappingMode.get(parentDocumentId)) {
                 case MAP_BY_MTP_IDENTIFIER:
                     heuristic = false;
                     mapColumn = COLUMN_STORAGE_ID;
@@ -109,16 +106,14 @@
             }
             final ContentValues[] valuesList = new ContentValues[roots.length];
             for (int i = 0; i < roots.length; i++) {
-                if (roots[i].mDeviceId != deviceId) {
-                    throw new IllegalArgumentException();
-                }
                 valuesList[i] = new ContentValues();
-                MtpDatabase.getRootDocumentValues(valuesList[i], resources, roots[i]);
+                MtpDatabase.getStorageDocumentValues(
+                        valuesList[i], resources, parentDocumentId, roots[i]);
             }
             final boolean changed = putDocuments(
                     valuesList,
-                    SELECTION_ROOT_DOCUMENTS,
-                    Integer.toString(deviceId),
+                    COLUMN_PARENT_DOCUMENT_ID + "=?",
+                    strings(parentDocumentId),
                     heuristic,
                     mapColumn);
             final ContentValues values = new ContentValues();
@@ -156,9 +151,8 @@
     synchronized void putChildDocuments(int deviceId, String parentId, MtpObjectInfo[] documents) {
         final boolean heuristic;
         final String mapColumn;
-        final String key = getChildDocumentsMappingStateKey(parentId);
-        Preconditions.checkState(mMappingMode.containsKey(key));
-        switch (mMappingMode.get(key)) {
+        Preconditions.checkState(mMappingMode.containsKey(parentId));
+        switch (mMappingMode.get(parentId)) {
             case MAP_BY_MTP_IDENTIFIER:
                 heuristic = false;
                 mapColumn = COLUMN_OBJECT_HANDLE;
@@ -173,63 +167,15 @@
         final ContentValues[] valuesList = new ContentValues[documents.length];
         for (int i = 0; i < documents.length; i++) {
             valuesList[i] = new ContentValues();
-            MtpDatabase.getChildDocumentValues(
+            MtpDatabase.getObjectDocumentValues(
                     valuesList[i], deviceId, parentId, documents[i]);
         }
         putDocuments(
-                valuesList, SELECTION_CHILD_DOCUMENTS, parentId, heuristic, mapColumn);
-    }
-
-    /**
-     * Stops adding root documents.
-     * @param deviceId Device ID.
-     * @return True if new rows are added/removed.
-     */
-    synchronized boolean stopAddingRootDocuments(int deviceId) {
-        final String key = getRootDocumentsMappingStateKey(deviceId);
-        Preconditions.checkState(mMappingMode.containsKey(key));
-        switch (mMappingMode.get(key)) {
-            case MAP_BY_MTP_IDENTIFIER:
-                mMappingMode.remove(key);
-                return stopAddingDocuments(
-                        SELECTION_ROOT_DOCUMENTS,
-                        Integer.toString(deviceId),
-                        COLUMN_STORAGE_ID);
-            case MAP_BY_NAME:
-                mMappingMode.remove(key);
-                return stopAddingDocuments(
-                        SELECTION_ROOT_DOCUMENTS,
-                        Integer.toString(deviceId),
-                        Document.COLUMN_DISPLAY_NAME);
-            default:
-                throw new Error("Unexpected mapping state.");
-        }
-    }
-
-    /**
-     * Stops adding documents under the parent.
-     * @param parentId Document ID of the parent.
-     */
-    synchronized void stopAddingChildDocuments(String parentId) {
-        final String key = getChildDocumentsMappingStateKey(parentId);
-        Preconditions.checkState(mMappingMode.containsKey(key));
-        switch (mMappingMode.get(key)) {
-            case MAP_BY_MTP_IDENTIFIER:
-                stopAddingDocuments(
-                        SELECTION_CHILD_DOCUMENTS,
-                        parentId,
-                        COLUMN_OBJECT_HANDLE);
-                break;
-            case MAP_BY_NAME:
-                stopAddingDocuments(
-                        SELECTION_CHILD_DOCUMENTS,
-                        parentId,
-                        Document.COLUMN_DISPLAY_NAME);
-                break;
-            default:
-                throw new Error("Unexpected mapping state.");
-        }
-        mMappingMode.remove(key);
+                valuesList,
+                COLUMN_PARENT_DOCUMENT_ID + "=?",
+                strings(parentId),
+                heuristic,
+                mapColumn);
     }
 
     @VisibleForTesting
@@ -257,31 +203,42 @@
      * identifier or not. If all the documents have MTP identifier, it uses the identifier to find
      * a corresponding existing row. Otherwise it does heuristic.
      *
-     * @param selection Query matches valid documents.
-     * @param arg Argument for selection.
-     * @return Mapping mode.
+     * @param parentDocumentId Parent document ID or NULL for root documents.
      */
-    private int startAddingDocuments(String selection, String arg) {
+    void startAddingDocuments(@Nullable String parentDocumentId) {
+        Preconditions.checkState(!mMappingMode.containsKey(parentDocumentId));
+        final String selection;
+        final String[] args;
+        if (parentDocumentId != null) {
+            selection = COLUMN_PARENT_DOCUMENT_ID + " = ?";
+            args = strings(parentDocumentId);
+        } else {
+            selection = COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
+            args = EMPTY_ARGS;
+        }
+
         final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
         database.beginTransaction();
         try {
             // Delete all pending rows.
             mDatabase.deleteDocumentsAndRootsRecursively(
-                    selection + " AND " + COLUMN_ROW_STATE + "=?", strings(arg, ROW_STATE_PENDING));
+                    selection + " AND " + COLUMN_ROW_STATE + "=?",
+                    DatabaseUtils.appendSelectionArgs(args, strings(ROW_STATE_PENDING)));
 
             // Set all documents as invalidated.
             final ContentValues values = new ContentValues();
             values.put(COLUMN_ROW_STATE, ROW_STATE_INVALIDATED);
-            database.update(TABLE_DOCUMENTS, values, selection, new String[] { arg });
+            database.update(TABLE_DOCUMENTS, values, selection, args);
 
             // If we have rows that does not have MTP identifier, do heuristic mapping by name.
             final boolean useNameForResolving = DatabaseUtils.queryNumEntries(
                     database,
                     TABLE_DOCUMENTS,
                     selection + " AND " + COLUMN_STORAGE_ID + " IS NULL",
-                    new String[] { arg }) > 0;
+                    args) > 0;
             database.setTransactionSuccessful();
-            return useNameForResolving ? MAP_BY_NAME : MAP_BY_MTP_IDENTIFIER;
+            mMappingMode.put(
+                    parentDocumentId, useNameForResolving ? MAP_BY_NAME : MAP_BY_MTP_IDENTIFIER);
         } finally {
             database.endTransaction();
         }
@@ -292,19 +249,19 @@
      * If the mapping mode is not heuristic, it just adds the rows to the database or updates the
      * existing rows with the new values. If the mapping mode is heuristic, it adds some new rows as
      * 'pending' state when that rows may be corresponding to existing 'invalidated' rows. Then
-     * {@link #stopAddingDocuments(String, String, String)} turns the pending rows into 'valid'
+     * {@link #stopAddingDocuments(String, String[], String)} turns the pending rows into 'valid'
      * rows. If the methods adds rows to database, it updates valueList with correct document ID.
      *
      * @param valuesList Values for documents to be stored in the database.
      * @param selection SQL where closure to select rows that shares the same parent.
-     * @param arg Argument for selection SQL.
+     * @param args Argument for selection SQL.
      * @param heuristic Whether the mapping mode is heuristic.
      * @return Whether the method adds new rows.
      */
     private boolean putDocuments(
             ContentValues[] valuesList,
             String selection,
-            String arg,
+            String[] args,
             boolean heuristic,
             String mappingKey) {
         final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
@@ -318,7 +275,9 @@
                         selection + " AND " +
                         COLUMN_ROW_STATE + "=? AND " +
                         mappingKey + "=?",
-                        strings(arg, ROW_STATE_INVALIDATED, values.getAsString(mappingKey)),
+                        DatabaseUtils.appendSelectionArgs(
+                                args,
+                                strings(ROW_STATE_INVALIDATED, values.getAsString(mappingKey))),
                         null,
                         null,
                         null,
@@ -362,12 +321,32 @@
      * Maps 'pending' document and 'invalidated' document that shares the same column of groupKey.
      * If the database does not find corresponding 'invalidated' document, it just removes
      * 'invalidated' document from the database.
-     * @param selection Query to select rows for resolving.
-     * @param arg Argument for selection SQL.
-     * @param groupKey Column name used to find corresponding rows.
+     * @param parentId Parent document ID or null for root documents.
      * @return Whether the methods adds or removed visible rows.
      */
-    private boolean stopAddingDocuments(String selection, String arg, String groupKey) {
+    boolean stopAddingDocuments(@Nullable String parentId) {
+        Preconditions.checkState(mMappingMode.containsKey(parentId));
+        final String selection;
+        final String[] args;
+        if (parentId != null) {
+            selection = COLUMN_PARENT_DOCUMENT_ID + "=?";
+            args = strings(parentId);
+        } else {
+            selection = COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
+            args = EMPTY_ARGS;
+        }
+        final String groupKey;
+        switch (mMappingMode.get(parentId)) {
+            case MAP_BY_MTP_IDENTIFIER:
+                groupKey = parentId != null ? COLUMN_OBJECT_HANDLE : COLUMN_STORAGE_ID;
+                break;
+            case MAP_BY_NAME:
+                groupKey = Document.COLUMN_DISPLAY_NAME;
+                break;
+            default:
+                throw new Error("Unexpected mapping state.");
+        }
+        mMappingMode.remove(parentId);
         final SQLiteDatabase database = mDatabase.getSQLiteDatabase();
         database.beginTransaction();
         try {
@@ -390,7 +369,7 @@
                             "group_concat(" + pendingIdQuery + ")"
                     },
                     selection,
-                    strings(arg),
+                    args,
                     groupKey,
                     "count(" + invalidatedIdQuery + ") = 1 AND count(" + pendingIdQuery + ") = 1",
                     null);
@@ -439,7 +418,7 @@
             // Delete all invalidated rows that cannot be mapped.
             if (mDatabase.deleteDocumentsAndRootsRecursively(
                     COLUMN_ROW_STATE + " = ? AND " + selection,
-                    strings(ROW_STATE_INVALIDATED, arg))) {
+                    DatabaseUtils.appendSelectionArgs(strings(ROW_STATE_INVALIDATED), args))) {
                 changed = true;
             }
 
@@ -452,7 +431,7 @@
                     TABLE_DOCUMENTS,
                     values,
                     COLUMN_ROW_STATE + " = ? AND " + selection,
-                    strings(ROW_STATE_PENDING, arg)) != 0) {
+                    DatabaseUtils.appendSelectionArgs(strings(ROW_STATE_PENDING), args)) != 0) {
                 changed = true;
             }
             database.setTransactionSuccessful();
@@ -494,20 +473,4 @@
         return "CASE WHEN " + COLUMN_ROW_STATE + " = " + Integer.toString(state) +
                 " THEN " + a + " ELSE NULL END";
     }
-
-    /**
-     * @param deviceId Device ID.
-     * @return Key for {@link #mMappingMode}.
-     */
-    private static String getRootDocumentsMappingStateKey(int deviceId) {
-        return "RootDocuments/" + deviceId;
-    }
-
-    /**
-     * @param parentDocumentId Document ID for the parent document.
-     * @return Key for {@link #mMappingMode}.
-     */
-    private static String getChildDocumentsMappingStateKey(String parentDocumentId) {
-        return "ChildDocuments/" + parentDocumentId;
-    }
 }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 0e91fdd..1ba3e31 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.Cursor;
+import android.database.MatrixCursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.database.sqlite.SQLiteQueryBuilder;
@@ -35,9 +36,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.FileNotFoundException;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Objects;
-import java.util.Set;
 
 /**
  * Database for MTP objects.
@@ -53,13 +54,13 @@
  * by comparing the directory structure and object name.
  *
  * To start putting documents into the database, the client needs to call
- * {@link Mapper#startAddingChildDocuments(String)} with the parent document ID. Also it
- * needs to call {@link Mapper#stopAddingChildDocuments(String)} after putting all child
+ * {@link Mapper#startAddingDocuments(String)} with the parent document ID. Also it
+ * needs to call {@link Mapper#stopAddingDocuments(String)} after putting all child
  * documents to the database. (All explanations are same for root documents)
  *
- * database.getMapper().startAddingChildDocuments();
+ * database.getMapper().startAddingDocuments();
  * database.getMapper().putChildDocuments();
- * database.getMapper().stopAddingChildDocuments();
+ * database.getMapper().stopAddingDocuments();
  *
  * To update the existing documents, the client code can repeat to call the three methods again.
  * The newly added rows update corresponding existing rows that have same MTP identifier like
@@ -107,11 +108,14 @@
      * @return Database cursor.
      */
     Cursor queryRoots(String[] columnNames) {
-        return mDatabase.query(
-                VIEW_ROOTS,
+        final SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
+        builder.setTables(JOIN_ROOTS);
+        builder.setProjectionMap(COLUMN_MAP_ROOTS);
+        return builder.query(
+                mDatabase,
                 columnNames,
-                COLUMN_ROW_STATE + " IN (?, ?)",
-                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED),
+                COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_DOCUMENT_TYPE + " = ?",
+                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_STORAGE),
                 null,
                 null,
                 null);
@@ -128,8 +132,8 @@
         return mDatabase.query(
                 TABLE_DOCUMENTS,
                 columnNames,
-                COLUMN_ROW_STATE + " IN (?, ?)",
-                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED),
+                COLUMN_ROW_STATE + " IN (?, ?) AND " + COLUMN_DOCUMENT_TYPE + "=?",
+                strings(ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_STORAGE),
                 null,
                 null,
                 null);
@@ -216,7 +220,7 @@
      */
     String putNewDocument(int deviceId, String parentDocumentId, MtpObjectInfo info) {
         final ContentValues values = new ContentValues();
-        getChildDocumentValues(values, deviceId, parentDocumentId, info);
+        getObjectDocumentValues(values, deviceId, parentDocumentId, info);
         mDatabase.beginTransaction();
         try {
             final long id = mDatabase.insert(TABLE_DOCUMENTS, null, values);
@@ -307,32 +311,6 @@
         }
     }
 
-    /**
-     * Returns the set of device ID stored in the database.
-     */
-    int[] getDeviceIds() {
-        final Cursor cursor = mDatabase.query(
-                true,
-                TABLE_DOCUMENTS,
-                strings(COLUMN_DEVICE_ID),
-                null,
-                null,
-                null,
-                null,
-                null,
-                null);
-        try {
-            final int[] ids = new int[cursor.getCount()];
-            for (int i = 0; i < ids.length; i++) {
-                cursor.moveToNext();
-                ids[i] = cursor.getInt(0);
-            }
-            return ids;
-        } finally {
-            cursor.close();
-        }
-    }
-
     private boolean deleteDocumentsAndRoots(String selection, String[] args) {
         mDatabase.beginTransaction();
         try {
@@ -370,7 +348,6 @@
         public void onCreate(SQLiteDatabase db) {
             db.execSQL(QUERY_CREATE_DOCUMENTS);
             db.execSQL(QUERY_CREATE_ROOT_EXTRA);
-            db.execSQL(QUERY_CREATE_VIEW_ROOTS);
         }
 
         @Override
@@ -384,18 +361,41 @@
         context.deleteDatabase(DATABASE_NAME);
     }
 
+    static void getDeviceDocumentValues(
+            ContentValues values, int deviceId, String name, MtpRoot[] roots) {
+        values.clear();
+        values.put(COLUMN_DEVICE_ID, deviceId);
+        values.putNull(COLUMN_STORAGE_ID);
+        values.putNull(COLUMN_OBJECT_HANDLE);
+        values.putNull(COLUMN_PARENT_DOCUMENT_ID);
+        values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
+        values.put(COLUMN_DOCUMENT_TYPE, DOCUMENT_TYPE_DEVICE);
+        values.put(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
+        values.put(Document.COLUMN_DISPLAY_NAME, name);
+        values.putNull(Document.COLUMN_SUMMARY);
+        values.putNull(Document.COLUMN_LAST_MODIFIED);
+        values.put(Document.COLUMN_ICON, R.drawable.ic_root_mtp);
+        values.put(Document.COLUMN_FLAGS, 0);
+        long size = 0;
+        for (final MtpRoot root : roots) {
+            size += root.mMaxCapacity - root.mFreeSpace;
+        }
+        values.put(Document.COLUMN_SIZE, size);
+    }
+
     /**
      * Gets {@link ContentValues} for the given root.
      * @param values {@link ContentValues} that receives values.
      * @param resources Resources used to get localized root name.
      * @param root Root to be converted {@link ContentValues}.
      */
-    static void getRootDocumentValues(ContentValues values, Resources resources, MtpRoot root) {
+    static void getStorageDocumentValues(
+            ContentValues values, Resources resources, String parentDocumentId, MtpRoot root) {
         values.clear();
         values.put(COLUMN_DEVICE_ID, root.mDeviceId);
         values.put(COLUMN_STORAGE_ID, root.mStorageId);
         values.putNull(COLUMN_OBJECT_HANDLE);
-        values.putNull(COLUMN_PARENT_DOCUMENT_ID);
+        values.put(COLUMN_PARENT_DOCUMENT_ID, parentDocumentId);
         values.put(COLUMN_ROW_STATE, ROW_STATE_VALID);
         values.put(COLUMN_DOCUMENT_TYPE, DOCUMENT_TYPE_STORAGE);
         values.put(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
@@ -415,7 +415,7 @@
      * @param parentId Parent document ID of the object.
      * @param info MTP object info.
      */
-    static void getChildDocumentValues(
+    static void getObjectDocumentValues(
             ContentValues values, int deviceId, String parentId, MtpObjectInfo info) {
         values.clear();
         final String mimeType = info.getFormat() == MtpConstants.FORMAT_ASSOCIATION ?
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
index 72bd6ee..a233589 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java
@@ -16,9 +16,13 @@
 
 package com.android.mtp;
 
+import android.database.sqlite.SQLiteQueryBuilder;
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Root;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Class containing MtpDatabase constants.
  */
@@ -41,9 +45,13 @@
     static final String TABLE_ROOT_EXTRA = "RootExtra";
 
     /**
-     * View to join Documents and RootExtra tables to provide roots information.
+     * 'FROM' closure of joining TABLE_DOCUMENTS and TABLE_ROOT_EXTRA.
      */
-    static final String VIEW_ROOTS = "Roots";
+    static final String JOIN_ROOTS = createJoinFromClosure(
+            TABLE_DOCUMENTS,
+            TABLE_ROOT_EXTRA,
+            Document.COLUMN_DOCUMENT_ID,
+            Root.COLUMN_ROOT_ID);
 
     static final String COLUMN_DEVICE_ID = "device_id";
     static final String COLUMN_STORAGE_ID = "storage_id";
@@ -86,8 +94,6 @@
 
     /**
      * Document that represents a MTP device.
-     * Note we have "device" document only when the device has multiple storage volumes. Otherwise
-     * we regard the single "storage" document as root.
      */
     static final int DOCUMENT_TYPE_DEVICE = 0;
 
@@ -103,9 +109,6 @@
 
     static final String SELECTION_DOCUMENT_ID = Document.COLUMN_DOCUMENT_ID + " = ?";
     static final String SELECTION_ROOT_ID = Root.COLUMN_ROOT_ID + " = ?";
-    static final String SELECTION_ROOT_DOCUMENTS =
-            COLUMN_DEVICE_ID + " = ? AND " + COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
-    static final String SELECTION_CHILD_DOCUMENTS = COLUMN_PARENT_DOCUMENT_ID + " = ?";
 
     static final String QUERY_CREATE_DOCUMENTS =
             "CREATE TABLE " + TABLE_DOCUMENTS + " (" +
@@ -134,30 +137,31 @@
             Root.COLUMN_MIME_TYPES + " TEXT NOT NULL);";
 
     /**
-     * Creates a view to join Documents table and RootExtra table on their primary keys to
-     * provide DocumentContract.Root equivalent information.
+     * Map for columns names to provide DocumentContract.Root compatible columns.
+     * @see SQLiteQueryBuilder#setProjectionMap(Map)
      */
-    static final String QUERY_CREATE_VIEW_ROOTS =
-            "CREATE VIEW " + VIEW_ROOTS + " AS SELECT " +
-                    TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID + " AS " +
-                            Root.COLUMN_ROOT_ID + "," +
-                    TABLE_ROOT_EXTRA + "." + Root.COLUMN_FLAGS + "," +
-                    TABLE_DOCUMENTS + "." + Document.COLUMN_ICON + " AS " +
-                            Root.COLUMN_ICON + "," +
-                    TABLE_DOCUMENTS + "." + Document.COLUMN_DISPLAY_NAME + " AS " +
-                            Root.COLUMN_TITLE + "," +
-                    TABLE_DOCUMENTS + "." + Document.COLUMN_SUMMARY + " AS " +
-                            Root.COLUMN_SUMMARY + "," +
-                    TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID + " AS " +
-                    Root.COLUMN_DOCUMENT_ID + "," +
-                    TABLE_ROOT_EXTRA + "." + Root.COLUMN_AVAILABLE_BYTES + "," +
-                    TABLE_ROOT_EXTRA + "." + Root.COLUMN_CAPACITY_BYTES + "," +
-                    TABLE_ROOT_EXTRA + "." + Root.COLUMN_MIME_TYPES + "," +
-                    TABLE_DOCUMENTS + "." + COLUMN_ROW_STATE +
-            " FROM " + TABLE_DOCUMENTS + " INNER JOIN " + TABLE_ROOT_EXTRA +
-            " ON " +
-                    COLUMN_PARENT_DOCUMENT_ID + " IS NULL AND " +
-                    TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID +
-                    "=" +
-                    TABLE_ROOT_EXTRA + "." + Root.COLUMN_ROOT_ID;
+    static final Map<String, String> COLUMN_MAP_ROOTS;
+    static {
+        COLUMN_MAP_ROOTS = new HashMap<>();
+        COLUMN_MAP_ROOTS.put(Root.COLUMN_ROOT_ID, TABLE_ROOT_EXTRA + "." + Root.COLUMN_ROOT_ID);
+        COLUMN_MAP_ROOTS.put(Root.COLUMN_FLAGS, TABLE_ROOT_EXTRA + "." + Root.COLUMN_FLAGS);
+        COLUMN_MAP_ROOTS.put(Root.COLUMN_ICON, TABLE_DOCUMENTS + "." + Document.COLUMN_ICON);
+        COLUMN_MAP_ROOTS.put(
+                Root.COLUMN_TITLE, TABLE_DOCUMENTS + "." + Document.COLUMN_DISPLAY_NAME);
+        COLUMN_MAP_ROOTS.put(Root.COLUMN_SUMMARY, TABLE_DOCUMENTS + "." + Document.COLUMN_SUMMARY);
+        COLUMN_MAP_ROOTS.put(
+                Root.COLUMN_DOCUMENT_ID, TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID);
+        COLUMN_MAP_ROOTS.put(
+                Root.COLUMN_AVAILABLE_BYTES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_AVAILABLE_BYTES);
+        COLUMN_MAP_ROOTS.put(
+                Root.COLUMN_CAPACITY_BYTES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_CAPACITY_BYTES);
+        COLUMN_MAP_ROOTS.put(
+                Root.COLUMN_MIME_TYPES, TABLE_ROOT_EXTRA + "." + Root.COLUMN_MIME_TYPES);
+    }
+
+    private static String createJoinFromClosure(
+            String table1, String table2, String column1, String column2) {
+        return table1 + " INNER JOIN " + table2 +
+                " ON " + table1 + "." + column1 + " = " + table2 + "." + column2;
+    }
 }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index d5f00e6..caa2024 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -190,9 +190,6 @@
             getDocumentLoader(parentIdentifier).clearTask(parentIdentifier);
             notifyChildDocumentsChange(parentIdentifier.mDocumentId);
         } catch (IOException error) {
-            for (final StackTraceElement element : error.getStackTrace()) {
-                Log.e("hirono", element.toString());
-            }
             throw new FileNotFoundException(error.getMessage());
         }
     }
@@ -293,19 +290,11 @@
     }
 
     /**
-     * Reopens MTP devices based on database state.
+     * Clears MTP identifier in the database.
      */
     private void resume() {
         synchronized (mDeviceListLock) {
             mDatabase.getMapper().clearMapping();
-            final int[] ids = mDatabase.getDeviceIds();
-            for (final int id : ids) {
-                try {
-                    openDevice(id);
-                } catch (IOException exception) {
-                    mDatabase.removeDeviceRows(id);
-                }
-            }
         }
     }
 
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
index df2ab01..197dec8 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
@@ -7,8 +7,11 @@
 import android.os.Process;
 import android.provider.DocumentsContract;
 import android.util.Log;
+import android.util.SparseArray;
 
 import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.FutureTask;
@@ -106,30 +109,42 @@
             int pollingCount = 0;
             while (!Thread.interrupted()) {
                 final int[] deviceIds = mManager.getOpenedDeviceIds();
-                if (deviceIds.length == 0) {
-                    return;
-                }
+                final Map<String, MtpRoot[]> rootsMap = new HashMap<>();
                 boolean changed = false;
-                for (int deviceId : deviceIds) {
+
+                // Update devices.
+                mDatabase.getMapper().startAddingDocuments(null /* parentDocumentId */);
+                for (final int deviceId : deviceIds) {
                     try {
                         final MtpRoot[] roots = mManager.getRoots(deviceId);
-                        mDatabase.getMapper().startAddingRootDocuments(deviceId);
-                        try {
-                            if (mDatabase.getMapper().putRootDocuments(
-                                    deviceId, mResources, roots)) {
-                                changed = true;
-                            }
-                        } finally {
-                            if (mDatabase.getMapper().stopAddingRootDocuments(deviceId)) {
-                                changed = true;
-                            }
+                        final String id = mDatabase.getMapper().putDeviceDocument(
+                                deviceId,
+                                mManager.getDeviceName(deviceId),
+                                roots);
+                        if (id != null) {
+                            changed = true;
+                            rootsMap.put(id, roots);
                         }
-                    } catch (IOException | SQLiteException exception) {
+                    } catch (IOException exception) {
                         // The error may happen on the device. We would like to continue getting
                         // roots for other devices.
                         Log.e(MtpDocumentsProvider.TAG, exception.getMessage());
                     }
                 }
+                mDatabase.getMapper().stopAddingDocuments(null /* parentDocumentId */);
+
+                // Update roots.
+                for (final String documentId : rootsMap.keySet()) {
+                    mDatabase.getMapper().startAddingDocuments(documentId);
+                    if (mDatabase.getMapper().putRootDocuments(
+                            documentId, mResources, rootsMap.get(documentId))) {
+                        changed = true;
+                    }
+                    if (mDatabase.getMapper().stopAddingDocuments(documentId)) {
+                        changed = true;
+                    }
+                }
+
                 if (changed) {
                     notifyChange();
                 }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
index f0b4343..7bd9a17 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
@@ -40,11 +40,11 @@
     @Override
     public void setUp() {
         mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, new TestResources(), new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", new TestResources(), new MtpRoot[] {
                 new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "")
         });
-        mDatabase.getMapper().stopAddingRootDocuments(0);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
         mManager = new BlockableTestMtpManager(getContext());
         mResolver = new TestContentResolver();
         mLoader = new DocumentLoader(mManager, mResolver, mDatabase);
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index 8166de1..6d57c5b 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -27,7 +27,9 @@
 
 import java.io.FileNotFoundException;
 
+import static android.provider.DocumentsContract.Document.*;
 import static com.android.mtp.MtpDatabase.strings;
+import static com.android.mtp.MtpDatabaseConstants.*;
 
 @SmallTest
 public class MtpDatabaseTest extends AndroidTestCase {
@@ -60,9 +62,21 @@
         mDatabase = null;
     }
 
+    private static int getInt(Cursor cursor, String columnName) {
+        return cursor.getInt(cursor.getColumnIndex(columnName));
+    }
+
+    private static boolean isNull(Cursor cursor, String columnName) {
+        return cursor.isNull(cursor.getColumnIndex(columnName));
+    }
+
+    private static String getString(Cursor cursor, String columnName) {
+        return cursor.getString(cursor.getColumnIndex(columnName));
+    }
+
     public void testPutRootDocuments() throws Exception {
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 1, "Device", "Storage", 1000, 2000, ""),
                 new MtpRoot(0, 2, "Device", "Storage", 2000, 4000, ""),
                 new MtpRoot(0, 3, "Device", "/@#%&<>Storage", 3000, 6000,"")
@@ -73,27 +87,27 @@
             assertEquals(3, cursor.getCount());
 
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertEquals("deviceId", 0, cursor.getInt(1));
-            assertEquals("storageId", 1, cursor.getInt(2));
-            assertTrue("objectHandle", cursor.isNull(3));
-            assertEquals("mimeType", DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(4));
-            assertEquals("displayName", "Device Storage", cursor.getString(5));
-            assertTrue("summary", cursor.isNull(6));
-            assertTrue("lastModified", cursor.isNull(7));
-            assertEquals("icon", R.drawable.ic_root_mtp, cursor.getInt(8));
-            assertEquals("flag", 0, cursor.getInt(9));
-            assertEquals("size", 1000, cursor.getInt(10));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
+            assertEquals(1, getInt(cursor, COLUMN_STORAGE_ID));
+            assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
+            assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, getString(cursor, COLUMN_MIME_TYPE));
+            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
+            assertTrue(isNull(cursor, COLUMN_SUMMARY));
+            assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
+            assertEquals(R.drawable.ic_root_mtp, getInt(cursor, COLUMN_ICON));
+            assertEquals(0, getInt(cursor, COLUMN_FLAGS));
+            assertEquals(1000, getInt(cursor, COLUMN_SIZE));
             assertEquals(
-                    "documentType", MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE, cursor.getInt(11));
+                    MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE, getInt(cursor, COLUMN_DOCUMENT_TYPE));
 
             cursor.moveToNext();
-            assertEquals("documentId", 2, cursor.getInt(0));
-            assertEquals("displayName", "Device Storage", cursor.getString(5));
+            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
 
             cursor.moveToNext();
-            assertEquals("documentId", 3, cursor.getInt(0));
-            assertEquals("displayName", "Device /@#%&<>Storage", cursor.getString(5));
+            assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals("Device /@#%&<>Storage", getString(cursor, COLUMN_DISPLAY_NAME));
 
             cursor.close();
         }
@@ -155,7 +169,7 @@
     }
 
     public void testPutChildDocuments() throws Exception {
-        mDatabase.getMapper().startAddingChildDocuments("parentId");
+        mDatabase.getMapper().startAddingDocuments("parentId");
         mDatabase.getMapper().putChildDocuments(0, "parentId", new MtpObjectInfo[] {
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                 createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
@@ -166,61 +180,61 @@
         assertEquals(3, cursor.getCount());
 
         cursor.moveToNext();
-        assertEquals("documentId", 1, cursor.getInt(0));
-        assertEquals("deviceId", 0, cursor.getInt(1));
-        assertEquals("storageId", 0, cursor.getInt(2));
-        assertEquals("objectHandle", 100, cursor.getInt(3));
-        assertEquals("mimeType", "text/plain", cursor.getString(4));
-        assertEquals("displayName", "note.txt", cursor.getString(5));
-        assertTrue("summary", cursor.isNull(6));
-        assertTrue("lastModified", cursor.isNull(7));
-        assertTrue("icon", cursor.isNull(8));
+        assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+        assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
+        assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
+        assertEquals(100, getInt(cursor, COLUMN_OBJECT_HANDLE));
+        assertEquals("text/plain", getString(cursor, COLUMN_MIME_TYPE));
+        assertEquals("note.txt", getString(cursor, COLUMN_DISPLAY_NAME));
+        assertTrue(isNull(cursor, COLUMN_SUMMARY));
+        assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
+        assertTrue(isNull(cursor, COLUMN_ICON));
         assertEquals(
-                "flag",
+                COLUMN_FLAGS,
                 DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
                 DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
                 cursor.getInt(9));
-        assertEquals("size", 1024, cursor.getInt(10));
+        assertEquals(1024, getInt(cursor, COLUMN_SIZE));
         assertEquals(
-                "documentType", MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, cursor.getInt(11));
+                MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));
 
         cursor.moveToNext();
-        assertEquals("documentId", 2, cursor.getInt(0));
-        assertEquals("deviceId", 0, cursor.getInt(1));
-        assertEquals("storageId", 0, cursor.getInt(2));
-        assertEquals("objectHandle", 101, cursor.getInt(3));
-        assertEquals("mimeType", "image/jpeg", cursor.getString(4));
-        assertEquals("displayName", "image.jpg", cursor.getString(5));
-        assertTrue("summary", cursor.isNull(6));
-        assertTrue("lastModified", cursor.isNull(7));
-        assertTrue("icon", cursor.isNull(8));
+        assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
+        assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
+        assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
+        assertEquals(101, getInt(cursor, COLUMN_OBJECT_HANDLE));
+        assertEquals("image/jpeg", getString(cursor, COLUMN_MIME_TYPE));
+        assertEquals("image.jpg", getString(cursor, COLUMN_DISPLAY_NAME));
+        assertTrue(isNull(cursor, COLUMN_SUMMARY));
+        assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
+        assertTrue(isNull(cursor, COLUMN_ICON));
         assertEquals(
-                "flag",
+                COLUMN_FLAGS,
                 DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
                 DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
                 cursor.getInt(9));
-        assertEquals("size", 2 * 1024 * 1024, cursor.getInt(10));
+        assertEquals(2 * 1024 * 1024, getInt(cursor, COLUMN_SIZE));
         assertEquals(
-                "documentType", MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, cursor.getInt(11));
+                MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));
 
         cursor.moveToNext();
-        assertEquals("documentId", 3, cursor.getInt(0));
-        assertEquals("deviceId", 0, cursor.getInt(1));
-        assertEquals("storageId", 0, cursor.getInt(2));
-        assertEquals("objectHandle", 102, cursor.getInt(3));
-        assertEquals("mimeType", "audio/mpeg", cursor.getString(4));
-        assertEquals("displayName", "music.mp3", cursor.getString(5));
-        assertTrue("summary", cursor.isNull(6));
-        assertTrue("lastModified", cursor.isNull(7));
-        assertTrue("icon", cursor.isNull(8));
+        assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
+        assertEquals(0, getInt(cursor, COLUMN_DEVICE_ID));
+        assertEquals(0, getInt(cursor, COLUMN_STORAGE_ID));
+        assertEquals(102, getInt(cursor, COLUMN_OBJECT_HANDLE));
+        assertEquals("audio/mpeg", getString(cursor, COLUMN_MIME_TYPE));
+        assertEquals("music.mp3", getString(cursor, COLUMN_DISPLAY_NAME));
+        assertTrue(isNull(cursor, COLUMN_SUMMARY));
+        assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
+        assertTrue(isNull(cursor, COLUMN_ICON));
         assertEquals(
-                "flag",
+                COLUMN_FLAGS,
                 DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
                 DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
                 cursor.getInt(9));
-        assertEquals("size", 3 * 1024 * 1024, cursor.getInt(10));
+        assertEquals(3 * 1024 * 1024, getInt(cursor, COLUMN_SIZE));
         assertEquals(
-                "documentType", MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, cursor.getInt(11));
+                MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT, getInt(cursor, COLUMN_DOCUMENT_TYPE));
 
         cursor.close();
     }
@@ -236,8 +250,8 @@
                 Root.COLUMN_AVAILABLE_BYTES
         };
 
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 100, "Device", "Storage A", 1000, 0, ""),
                 new MtpRoot(0, 101, "Device", "Storage B", 1001, 0, "")
         });
@@ -246,13 +260,13 @@
             final Cursor cursor = mDatabase.queryRootDocuments(columns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertEquals("storageId", 100, cursor.getInt(1));
-            assertEquals("name", "Device Storage A", cursor.getString(2));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
-            assertEquals("documentId", 2, cursor.getInt(0));
-            assertEquals("storageId", 101, cursor.getInt(1));
-            assertEquals("name", "Device Storage B", cursor.getString(2));
+            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(101, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
 
@@ -260,11 +274,11 @@
             final Cursor cursor = mDatabase.queryRoots(rootColumns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("rootId", 1, cursor.getInt(0));
-            assertEquals("availableBytes", 1000, cursor.getInt(1));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.moveToNext();
-            assertEquals("rootId", 2, cursor.getInt(0));
-            assertEquals("availableBytes", 1001, cursor.getInt(1));
+            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1001, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
 
@@ -274,13 +288,13 @@
             final Cursor cursor = mDatabase.queryRootDocuments(columns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertTrue("storageId", cursor.isNull(1));
-            assertEquals("name", "Device Storage A", cursor.getString(2));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertTrue(isNull(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
-            assertEquals("documentId", 2, cursor.getInt(0));
-            assertTrue("storageId", cursor.isNull(1));
-            assertEquals("name", "Device Storage B", cursor.getString(2));
+            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertTrue(isNull(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
 
@@ -288,16 +302,16 @@
             final Cursor cursor = mDatabase.queryRoots(rootColumns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("rootId", 1, cursor.getInt(0));
-            assertEquals("availableBytes", 1000, cursor.getInt(1));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.moveToNext();
-            assertEquals("rootId", 2, cursor.getInt(0));
-            assertEquals("availableBytes", 1001, cursor.getInt(1));
+            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1001, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
 
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 200, "Device", "Storage A", 2000, 0, ""),
                 new MtpRoot(0, 202, "Device", "Storage C", 2002, 0, "")
         });
@@ -306,17 +320,17 @@
             final Cursor cursor = mDatabase.queryRootDocuments(columns);
             assertEquals(3, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertTrue("storageId", cursor.isNull(1));
-            assertEquals("name", "Device Storage A", cursor.getString(2));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertTrue(isNull(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
-            assertEquals("documentId", 2, cursor.getInt(0));
-            assertTrue("storageId", cursor.isNull(1));
-            assertEquals("name", "Device Storage B", cursor.getString(2));
+            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertTrue(isNull(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
-            assertEquals("documentId", 4, cursor.getInt(0));
-            assertEquals("storageId", 202, cursor.getInt(1));
-            assertEquals("name", "Device Storage C", cursor.getString(2));
+            assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(202, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
 
@@ -324,30 +338,30 @@
             final Cursor cursor = mDatabase.queryRoots(rootColumns);
             assertEquals(3, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("rootId", 1, cursor.getInt(0));
-            assertEquals("availableBytes", 1000, cursor.getInt(1));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.moveToNext();
-            assertEquals("rootId", 2, cursor.getInt(0));
-            assertEquals("availableBytes", 1001, cursor.getInt(1));
+            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1001, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.moveToNext();
-            assertEquals("rootId", 4, cursor.getInt(0));
-            assertEquals("availableBytes", 2002, cursor.getInt(1));
+            assertEquals(4, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(2002, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
 
-        mDatabase.getMapper().stopAddingRootDocuments(0);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
         {
             final Cursor cursor = mDatabase.queryRootDocuments(columns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertEquals("storageId", 200, cursor.getInt(1));
-            assertEquals("name", "Device Storage A", cursor.getString(2));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage A", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
-            assertEquals("documentId", 4, cursor.getInt(0));
-            assertEquals("storageId", 202, cursor.getInt(1));
-            assertEquals("name", "Device Storage C", cursor.getString(2));
+            assertEquals(4, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(202, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage C", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
 
@@ -355,11 +369,11 @@
             final Cursor cursor = mDatabase.queryRoots(rootColumns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("rootId", 1, cursor.getInt(0));
-            assertEquals("availableBytes", 2000, cursor.getInt(1));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(2000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.moveToNext();
-            assertEquals("rootId", 4, cursor.getInt(0));
-            assertEquals("availableBytes", 2002, cursor.getInt(1));
+            assertEquals(4, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(2002, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
     }
@@ -370,7 +384,7 @@
                 MtpDatabaseConstants.COLUMN_OBJECT_HANDLE,
                 DocumentsContract.Document.COLUMN_DISPLAY_NAME
         };
-        mDatabase.getMapper().startAddingChildDocuments("parentId");
+        mDatabase.getMapper().startAddingDocuments("parentId");
         mDatabase.getMapper().putChildDocuments(0, "parentId", new MtpObjectInfo[] {
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                 createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
@@ -383,24 +397,24 @@
             assertEquals(3, cursor.getCount());
 
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertTrue("objectHandle", cursor.isNull(1));
-            assertEquals("name", "note.txt", cursor.getString(2));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
+            assertEquals("note.txt", getString(cursor, COLUMN_DISPLAY_NAME));
 
             cursor.moveToNext();
-            assertEquals("documentId", 2, cursor.getInt(0));
-            assertTrue("objectHandle", cursor.isNull(1));
-            assertEquals("name", "image.jpg", cursor.getString(2));
+            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
+            assertEquals("image.jpg", getString(cursor, COLUMN_DISPLAY_NAME));
 
             cursor.moveToNext();
-            assertEquals("documentId", 3, cursor.getInt(0));
-            assertTrue("objectHandle", cursor.isNull(1));
-            assertEquals("name", "music.mp3", cursor.getString(2));
+            assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
+            assertEquals("music.mp3", getString(cursor, COLUMN_DISPLAY_NAME));
 
             cursor.close();
         }
 
-        mDatabase.getMapper().startAddingChildDocuments("parentId");
+        mDatabase.getMapper().startAddingDocuments("parentId");
         mDatabase.getMapper().putChildDocuments(0, "parentId", new MtpObjectInfo[] {
                 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                 createDocument(203, "video.mp4", MtpConstants.FORMAT_MP4_CONTAINER, 1024),
@@ -411,28 +425,28 @@
             assertEquals(4, cursor.getCount());
 
             cursor.moveToPosition(3);
-            assertEquals("documentId", 5, cursor.getInt(0));
-            assertEquals("objectHandle", 203, cursor.getInt(1));
-            assertEquals("name", "video.mp4", cursor.getString(2));
+            assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(203, getInt(cursor, COLUMN_OBJECT_HANDLE));
+            assertEquals("video.mp4", getString(cursor, COLUMN_DISPLAY_NAME));
 
             cursor.close();
         }
 
-        mDatabase.getMapper().stopAddingChildDocuments("parentId");
+        mDatabase.getMapper().stopAddingDocuments("parentId");
 
         {
             final Cursor cursor = mDatabase.queryChildDocuments(columns, "parentId");
             assertEquals(2, cursor.getCount());
 
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertEquals("objectHandle", 200, cursor.getInt(1));
-            assertEquals("name", "note.txt", cursor.getString(2));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(200, getInt(cursor, COLUMN_OBJECT_HANDLE));
+            assertEquals("note.txt", getString(cursor, COLUMN_DISPLAY_NAME));
 
             cursor.moveToNext();
-            assertEquals("documentId", 5, cursor.getInt(0));
-            assertEquals("objectHandle", 203, cursor.getInt(1));
-            assertEquals("name", "video.mp4", cursor.getString(2));
+            assertEquals(5, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(203, getInt(cursor, COLUMN_OBJECT_HANDLE));
+            assertEquals("video.mp4", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
     }
@@ -447,12 +461,12 @@
                 Root.COLUMN_ROOT_ID,
                 Root.COLUMN_AVAILABLE_BYTES
         };
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().startAddingRootDocuments(1);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocIdA");
+        mDatabase.getMapper().startAddingDocuments("deviceDocIdB");
+        mDatabase.getMapper().putRootDocuments("deviceDocIdA", resources, new MtpRoot[] {
                 new MtpRoot(0, 100, "Device", "Storage", 0, 0, "")
         });
-        mDatabase.getMapper().putRootDocuments(1, resources, new MtpRoot[] {
+        mDatabase.getMapper().putRootDocuments("deviceDocIdB", resources, new MtpRoot[] {
                 new MtpRoot(1, 100, "Device", "Storage", 0, 0, "")
         });
 
@@ -460,13 +474,13 @@
             final Cursor cursor = mDatabase.queryRootDocuments(columns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertEquals("storageId", 100, cursor.getInt(1));
-            assertEquals("name", "Device Storage", cursor.getString(2));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
-            assertEquals("documentId", 2, cursor.getInt(0));
-            assertEquals("storageId", 100, cursor.getInt(1));
-            assertEquals("name", "Device Storage", cursor.getString(2));
+            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
 
@@ -474,38 +488,38 @@
             final Cursor cursor = mDatabase.queryRoots(rootColumns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("rootId", 1, cursor.getInt(0));
-            assertEquals("availableBytes", 0, cursor.getInt(1));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.moveToNext();
-            assertEquals("rootId", 2, cursor.getInt(0));
-            assertEquals("availableBytes", 0, cursor.getInt(1));
+            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(0, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
 
         mDatabase.getMapper().clearMapping();
 
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().startAddingRootDocuments(1);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocIdA");
+        mDatabase.getMapper().startAddingDocuments("deviceDocIdB");
+        mDatabase.getMapper().putRootDocuments("deviceDocIdA", resources, new MtpRoot[] {
                 new MtpRoot(0, 200, "Device", "Storage", 2000, 0, "")
         });
-        mDatabase.getMapper().putRootDocuments(1, resources, new MtpRoot[] {
+        mDatabase.getMapper().putRootDocuments("deviceDocIdB", resources, new MtpRoot[] {
                 new MtpRoot(1, 300, "Device", "Storage", 3000, 0, "")
         });
-        mDatabase.getMapper().stopAddingRootDocuments(0);
-        mDatabase.getMapper().stopAddingRootDocuments(1);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocIdA");
+        mDatabase.getMapper().stopAddingDocuments("deviceDocIdB");
 
         {
             final Cursor cursor = mDatabase.queryRootDocuments(columns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertEquals("storageId", 200, cursor.getInt(1));
-            assertEquals("name", "Device Storage", cursor.getString(2));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
-            assertEquals("documentId", 2, cursor.getInt(0));
-            assertEquals("storageId", 300, cursor.getInt(1));
-            assertEquals("name", "Device Storage", cursor.getString(2));
+            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
 
@@ -513,11 +527,11 @@
             final Cursor cursor = mDatabase.queryRoots(rootColumns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("rootId", 1, cursor.getInt(0));
-            assertEquals("availableBytes", 2000, cursor.getInt(1));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(2000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.moveToNext();
-            assertEquals("rootId", 2, cursor.getInt(0));
-            assertEquals("availableBytes", 3000, cursor.getInt(1));
+            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
     }
@@ -528,8 +542,8 @@
                 MtpDatabaseConstants.COLUMN_OBJECT_HANDLE
         };
 
-        mDatabase.getMapper().startAddingChildDocuments("parentId1");
-        mDatabase.getMapper().startAddingChildDocuments("parentId2");
+        mDatabase.getMapper().startAddingDocuments("parentId1");
+        mDatabase.getMapper().startAddingDocuments("parentId2");
         mDatabase.getMapper().putChildDocuments(0, "parentId1", new MtpObjectInfo[] {
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
         });
@@ -538,30 +552,30 @@
         });
         mDatabase.getMapper().clearMapping();
 
-        mDatabase.getMapper().startAddingChildDocuments("parentId1");
-        mDatabase.getMapper().startAddingChildDocuments("parentId2");
+        mDatabase.getMapper().startAddingDocuments("parentId1");
+        mDatabase.getMapper().startAddingDocuments("parentId2");
         mDatabase.getMapper().putChildDocuments(0, "parentId1", new MtpObjectInfo[] {
                 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
         });
         mDatabase.getMapper().putChildDocuments(0, "parentId2", new MtpObjectInfo[] {
                 createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
         });
-        mDatabase.getMapper().stopAddingChildDocuments("parentId1");
+        mDatabase.getMapper().stopAddingDocuments("parentId1");
 
         {
             final Cursor cursor = mDatabase.queryChildDocuments(columns, "parentId1");
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertEquals("objectHandle", 200, cursor.getInt(1));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(200, getInt(cursor, COLUMN_OBJECT_HANDLE));
             cursor.close();
         }
         {
             final Cursor cursor = mDatabase.queryChildDocuments(columns, "parentId2");
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("documentId", 2, cursor.getInt(0));
-            assertTrue("objectHandle", cursor.isNull(1));
+            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertTrue(isNull(cursor, COLUMN_OBJECT_HANDLE));
             cursor.close();
         }
     }
@@ -577,39 +591,39 @@
                 Root.COLUMN_AVAILABLE_BYTES
         };
 
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 100, "Device", "Storage", 0, 0, ""),
         });
         mDatabase.getMapper().clearMapping();
 
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 200, "Device", "Storage", 2000, 0, ""),
         });
         mDatabase.getMapper().clearMapping();
 
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 300, "Device", "Storage", 3000, 0, ""),
         });
-        mDatabase.getMapper().stopAddingRootDocuments(0);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
         {
             final Cursor cursor = mDatabase.queryRootDocuments(columns);
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertEquals("storageId", 300, cursor.getInt(1));
-            assertEquals("name", "Device Storage", cursor.getString(2));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(300, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
         {
             final Cursor cursor = mDatabase.queryRoots(rootColumns);
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("rootId", 1, cursor.getInt(0));
-            assertEquals("availableBytes", 3000, cursor.getInt(1));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(3000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
     }
@@ -625,41 +639,41 @@
                 Root.COLUMN_AVAILABLE_BYTES
         };
 
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 100, "Device", "Storage", 0, 0, ""),
         });
         mDatabase.getMapper().clearMapping();
 
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 200, "Device", "Storage", 2000, 0, ""),
                 new MtpRoot(0, 201, "Device", "Storage", 2001, 0, ""),
         });
-        mDatabase.getMapper().stopAddingRootDocuments(0);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
         {
             final Cursor cursor = mDatabase.queryRootDocuments(columns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("documentId", 2, cursor.getInt(0));
-            assertEquals("storageId", 200, cursor.getInt(1));
-            assertEquals("name", "Device Storage", cursor.getString(2));
+            assertEquals(2, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(200, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.moveToNext();
-            assertEquals("documentId", 3, cursor.getInt(0));
-            assertEquals("storageId", 201, cursor.getInt(1));
-            assertEquals("name", "Device Storage", cursor.getString(2));
+            assertEquals(3, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(201, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
         {
             final Cursor cursor = mDatabase.queryRoots(rootColumns);
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("rootId", 2, cursor.getInt(0));
-            assertEquals("availableBytes", 2000, cursor.getInt(1));
+            assertEquals(2, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(2000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.moveToNext();
-            assertEquals("rootId", 3, cursor.getInt(0));
-            assertEquals("availableBytes", 2001, cursor.getInt(1));
+            assertEquals(3, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(2001, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
     }
@@ -667,17 +681,17 @@
     public void testReplaceExistingRoots() {
         // The client code should be able to replace existing rows with new information.
         // Add one.
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
         });
-        mDatabase.getMapper().stopAddingRootDocuments(0);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
         // Replace it.
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 100, "Device", "Storage B", 1000, 1000, ""),
         });
-        mDatabase.getMapper().stopAddingRootDocuments(0);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
         {
             final String[] columns = new String[] {
                     DocumentsContract.Document.COLUMN_DOCUMENT_ID,
@@ -687,9 +701,9 @@
             final Cursor cursor = mDatabase.queryRootDocuments(columns);
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("documentId", 1, cursor.getInt(0));
-            assertEquals("storageId", 100, cursor.getInt(1));
-            assertEquals("name", "Device Storage B", cursor.getString(2));
+            assertEquals(1, getInt(cursor, COLUMN_DOCUMENT_ID));
+            assertEquals(100, getInt(cursor, COLUMN_STORAGE_ID));
+            assertEquals("Device Storage B", getString(cursor, COLUMN_DISPLAY_NAME));
             cursor.close();
         }
         {
@@ -700,8 +714,8 @@
             final Cursor cursor = mDatabase.queryRoots(columns);
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("rootId", 1, cursor.getInt(0));
-            assertEquals("availableBytes", 1000, cursor.getInt(1));
+            assertEquals(1, getInt(cursor, Root.COLUMN_ROOT_ID));
+            assertEquals(1000, getInt(cursor, Root.COLUMN_AVAILABLE_BYTES));
             cursor.close();
         }
     }
@@ -709,8 +723,8 @@
     public void testFailToReplaceExisitingUnmappedRoots() {
         // The client code should not be able to replace rows before resolving 'unmapped' rows.
         // Add one.
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
         });
         mDatabase.getMapper().clearMapping();
@@ -718,15 +732,15 @@
         assertEquals(1, oldCursor.getCount());
 
         // Add one.
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 101, "Device", "Storage B", 1000, 1000, ""),
         });
         // Add one more before resolving unmapped documents.
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 102, "Device", "Storage B", 1000, 1000, ""),
         });
-        mDatabase.getMapper().stopAddingRootDocuments(0);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
         // Because the roots shares the same name, the roots should have new IDs.
         final Cursor newCursor = mDatabase.queryRoots(strings(Root.COLUMN_ROOT_ID));
@@ -742,11 +756,11 @@
     }
 
     public void testQueryDocument() {
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
         });
-        mDatabase.getMapper().stopAddingRootDocuments(0);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
         final Cursor cursor = mDatabase.queryDocument("1", strings(Document.COLUMN_DISPLAY_NAME));
         assertEquals(1, cursor.getCount());
@@ -756,48 +770,48 @@
     }
 
     public void testGetParentId() throws FileNotFoundException {
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
         });
-        mDatabase.getMapper().stopAddingRootDocuments(0);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
-        mDatabase.getMapper().startAddingChildDocuments("1");
+        mDatabase.getMapper().startAddingDocuments("1");
         mDatabase.getMapper().putChildDocuments(
                 0,
                 "1",
                 new MtpObjectInfo[] {
                         createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                 });
-        mDatabase.getMapper().stopAddingChildDocuments("1");
+        mDatabase.getMapper().stopAddingDocuments("1");
 
         assertEquals("1", mDatabase.getParentId("2"));
     }
 
     public void testDeleteDocument() {
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
         });
-        mDatabase.getMapper().stopAddingRootDocuments(0);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
-        mDatabase.getMapper().startAddingChildDocuments("1");
+        mDatabase.getMapper().startAddingDocuments("1");
         mDatabase.getMapper().putChildDocuments(
                 0,
                 "1",
                 new MtpObjectInfo[] {
                         createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
                 });
-        mDatabase.getMapper().stopAddingChildDocuments("1");
+        mDatabase.getMapper().stopAddingDocuments("1");
 
-        mDatabase.getMapper().startAddingChildDocuments("2");
+        mDatabase.getMapper().startAddingDocuments("2");
         mDatabase.getMapper().putChildDocuments(
                 0,
                 "2",
                 new MtpObjectInfo[] {
                         createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                 });
-        mDatabase.getMapper().stopAddingChildDocuments("2");
+        mDatabase.getMapper().stopAddingDocuments("2");
 
         mDatabase.deleteDocument("2");
 
@@ -819,11 +833,11 @@
     }
 
     public void testPutNewDocument() {
-        mDatabase.getMapper().startAddingRootDocuments(0);
-        mDatabase.getMapper().putRootDocuments(0, resources, new MtpRoot[] {
+        mDatabase.getMapper().startAddingDocuments("deviceDocId");
+        mDatabase.getMapper().putRootDocuments("deviceDocId", resources, new MtpRoot[] {
                 new MtpRoot(0, 100, "Device", "Storage A", 0, 0, ""),
         });
-        mDatabase.getMapper().stopAddingRootDocuments(0);
+        mDatabase.getMapper().stopAddingDocuments("deviceDocId");
 
         assertEquals(
                 "2",
@@ -841,12 +855,12 @@
 
         // The new document should not be mapped with existing invalidated document.
         mDatabase.getMapper().clearMapping();
-        mDatabase.getMapper().startAddingChildDocuments("1");
+        mDatabase.getMapper().startAddingDocuments("1");
         mDatabase.putNewDocument(
                 0,
                 "1",
                 createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024));
-        mDatabase.getMapper().stopAddingChildDocuments("1");
+        mDatabase.getMapper().stopAddingDocuments("1");
 
         {
             final Cursor cursor =
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index dc6f79e..b0e9722 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -138,11 +138,11 @@
             final Cursor cursor = mProvider.queryRoots(null);
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("1", cursor.getString(0));
+            assertEquals("2", cursor.getString(0));
             assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
             assertEquals("Device A Storage A", cursor.getString(3));
-            assertEquals("1", cursor.getString(4));
+            assertEquals("2", cursor.getString(4));
             assertEquals(1024, cursor.getInt(5));
         }
 
@@ -153,11 +153,11 @@
             assertEquals(2, cursor.getCount());
             cursor.moveToNext();
             cursor.moveToNext();
-            assertEquals("2", cursor.getString(0));
+            assertEquals("4", cursor.getString(0));
             assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
             assertEquals("Device B Storage B", cursor.getString(3));
-            assertEquals("2", cursor.getString(4));
+            assertEquals("4", cursor.getString(4));
             assertEquals(2048, cursor.getInt(5));
         }
     }
@@ -185,11 +185,11 @@
             final Cursor cursor = mProvider.queryRoots(null);
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
-            assertEquals("1", cursor.getString(0));
+            assertEquals("2", cursor.getString(0));
             assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             assertEquals(R.drawable.ic_root_mtp, cursor.getInt(2));
             assertEquals("Device B Storage B", cursor.getString(3));
-            assertEquals("1", cursor.getString(4));
+            assertEquals("2", cursor.getString(4));
             assertEquals(2048, cursor.getInt(5));
         }
     }
@@ -216,12 +216,12 @@
                                 .build()
                 });
 
-        final Cursor cursor = mProvider.queryDocument("2", null);
+        final Cursor cursor = mProvider.queryDocument("3", null);
         assertEquals(1, cursor.getCount());
 
         cursor.moveToNext();
 
-        assertEquals("2", cursor.getString(0));
+        assertEquals("3", cursor.getString(0));
         assertEquals("image/jpeg", cursor.getString(1));
         assertEquals("image.jpg", cursor.getString(2));
         assertEquals(1422716400000L, cursor.getLong(3));
@@ -255,11 +255,11 @@
                                 .build()
                 });
 
-        final Cursor cursor = mProvider.queryDocument("2", null);
+        final Cursor cursor = mProvider.queryDocument("3", null);
         assertEquals(1, cursor.getCount());
 
         cursor.moveToNext();
-        assertEquals("2", cursor.getString(0));
+        assertEquals("3", cursor.getString(0));
         assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
         assertEquals("directory", cursor.getString(2));
         assertEquals(1422716400000L, cursor.getLong(3));
@@ -287,11 +287,11 @@
                         4096 /* total space */,
                         "" /* no volume identifier */)
         });
-        final Cursor cursor = mProvider.queryDocument("1", null);
+        final Cursor cursor = mProvider.queryDocument("2", null);
         assertEquals(1, cursor.getCount());
 
         cursor.moveToNext();
-        assertEquals("1", cursor.getString(0));
+        assertEquals("2", cursor.getString(0));
         assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
         assertEquals("Device A Storage A", cursor.getString(2));
         assertTrue(cursor.isNull(3));
@@ -325,7 +325,7 @@
         assertEquals(1, cursor.getCount());
 
         assertTrue(cursor.moveToNext());
-        assertEquals("2", cursor.getString(0));
+        assertEquals("3", cursor.getString(0));
         assertEquals("image/jpeg", cursor.getString(1));
         assertEquals("image.jpg", cursor.getString(2));
         assertEquals(0, cursor.getLong(3));
@@ -376,7 +376,7 @@
                     .build()
         });
 
-        mProvider.deleteDocument("2");
+        mProvider.deleteDocument("3");
         assertEquals(1, mResolver.getChangeCount(
                 DocumentsContract.buildChildDocumentsUri(
                         MtpDocumentsProvider.AUTHORITY, "1")));
@@ -398,7 +398,7 @@
                     .build()
         });
         try {
-            mProvider.deleteDocument("3");
+            mProvider.deleteDocument("4");
             fail();
         } catch (Throwable e) {
             assertTrue(e instanceof IOException);
@@ -408,34 +408,6 @@
                         MtpDocumentsProvider.AUTHORITY, "1")));
     }
 
-    @MediumTest
-    public void testPauseAndResume() throws Exception {
-        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_FILE);
-        mMtpManager.addValidDevice(0);
-        mProvider.openDevice(0);
-        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 0, 0, "")});
-
-        {
-            final Cursor cursor = mProvider.queryRoots(
-                    strings(DocumentsContract.Root.COLUMN_ROOT_ID));
-            cursor.moveToNext();
-            assertEquals(1, cursor.getInt(0));
-        }
-
-        mProvider.shutdown();
-        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_FILE);
-
-        {
-            // We can still fetch roots after relaunching the provider.
-            final Cursor cursor = mProvider.queryRoots(
-                    strings(DocumentsContract.Root.COLUMN_ROOT_ID));
-            assertEquals(1, cursor.getCount());
-            cursor.moveToNext();
-            assertEquals(1, cursor.getInt(0));
-            assertEquals(1, mMtpManager.getOpenedDeviceIds().length);
-        }
-    }
-
     private void setupProvider(int flag) {
         mDatabase = new MtpDatabase(getContext(), flag);
         mProvider = new MtpDocumentsProvider();
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
index 3833799..ddc18a4 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
@@ -196,4 +196,9 @@
         }
         return result;
     }
+
+    @Override
+    String getDeviceName(int deviceId) throws IOException {
+        return "Device";
+    }
 }
diff --git a/packages/SystemUI/res/layout/recents.xml b/packages/SystemUI/res/layout/recents.xml
index 2c010dd..16ff14c 100644
--- a/packages/SystemUI/res/layout/recents.xml
+++ b/packages/SystemUI/res/layout/recents.xml
@@ -33,12 +33,6 @@
         android:layout_height="match_parent">
     </com.android.systemui.recents.views.RecentsView>
 
-    <!-- Empty View -->
-    <ViewStub android:id="@+id/empty_view_stub"
-           android:layout="@layout/recents_empty"
-           android:layout_width="match_parent"
-           android:layout_height="match_parent" />
-
     <!-- History View -->
     <ViewStub android:id="@+id/history_view_stub"
            android:layout="@layout/recents_history"
diff --git a/packages/SystemUI/res/layout/recents_history_button.xml b/packages/SystemUI/res/layout/recents_history_button.xml
index 601c5ed..8c96fc6 100644
--- a/packages/SystemUI/res/layout/recents_history_button.xml
+++ b/packages/SystemUI/res/layout/recents_history_button.xml
@@ -26,5 +26,4 @@
     android:shadowDx="0"
     android:shadowDy="2"
     android:shadowRadius="5"
-    android:fontFamily="sans-serif-medium"
-    android:visibility="invisible" />
\ No newline at end of file
+    android:fontFamily="sans-serif-medium" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 666a024..9b74a80 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -713,8 +713,8 @@
     <string name="recents_launch_error_message">Could not start <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
     <!-- Recents: Show history string. [CHAR LIMIT=NONE] -->
     <string name="recents_show_history_button_label">More</string>
-    <!-- Recents: The history of recents. [CHAR LIMIT=NONE] -->
-    <string name="recents_history_label">History</string>
+    <!-- Recents: A format string to set the number of availabe historical tasks in recents. [CHAR LIMIT=NONE] -->
+    <string name="recents_history_label_format"><xliff:g id="number">%d</xliff:g> More</string>
 
     <!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] -->
     <string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 384b86f..1bc9a63 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -87,6 +87,9 @@
     private final static String TAG = "RecentsActivity";
     private final static boolean DEBUG = false;
 
+    private final static String KEY_SAVED_STATE_HISTORY_VISIBLE =
+            "saved_instance_state_history_visible";
+
     public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
 
     private RecentsPackageMonitor mPackageMonitor;
@@ -97,8 +100,6 @@
     // Top level views
     private RecentsView mRecentsView;
     private SystemBarScrimViews mScrimViews;
-    private ViewStub mEmptyViewStub;
-    private View mEmptyView;
     private ViewStub mHistoryViewStub;
     private RecentsHistoryView mHistoryView;
 
@@ -197,7 +198,6 @@
         loader.loadTasks(this, plan, loadOpts);
 
         TaskStack stack = plan.getTaskStack();
-        launchState.launchedWithNoRecentTasks = !plan.hasTasks();
         mRecentsView.setTaskStack(stack);
 
         // Mark the task that is the launch target
@@ -215,30 +215,13 @@
             }
         }
 
-        // Update the top level view's visibilities
-        if (launchState.launchedWithNoRecentTasks) {
-            if (mEmptyView == null) {
-                mEmptyView = mEmptyViewStub.inflate();
-            }
-            mEmptyView.setVisibility(View.VISIBLE);
-            if (!RecentsDebugFlags.Static.DisableSearchBar) {
-                mRecentsView.setSearchBarVisibility(View.GONE);
-            }
-        } else {
-            if (mEmptyView != null) {
-                mEmptyView.setVisibility(View.GONE);
-            }
-            if (!RecentsDebugFlags.Static.DisableSearchBar) {
-                if (mRecentsView.hasValidSearchBar()) {
-                    mRecentsView.setSearchBarVisibility(View.VISIBLE);
-                } else {
-                    refreshSearchWidgetView();
-                }
-            }
-        }
-
         // Animate the SystemUI scrims into view
-        mScrimViews.prepareEnterRecentsAnimation();
+        boolean hasStatusBarScrim = stack.getStackTaskCount() > 0;
+        boolean animateStatusBarScrim = launchState.launchedFromHome;
+        boolean hasNavBarScrim = (stack.getStackTaskCount() > 0) && !config.hasTransposedNavBar;
+        boolean animateNavBarScrim = true;
+        mScrimViews.prepareEnterRecentsAnimation(hasStatusBarScrim, animateStatusBarScrim, hasNavBarScrim,
+                animateNavBarScrim);
 
         // Keep track of whether we launched from the nav bar button or via alt-tab
         if (launchState.launchedWithAltTab) {
@@ -265,7 +248,10 @@
     boolean dismissHistory() {
         // Try and hide the history view first
         if (mHistoryView != null && mHistoryView.isVisible()) {
-            EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
+            ReferenceCountedTrigger t = new ReferenceCountedTrigger(this);
+            t.increment();
+            EventBus.getDefault().send(new HideHistoryEvent(true /* animate */, t));
+            t.decrement();
             return true;
         }
         return false;
@@ -374,7 +360,6 @@
         mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                 View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
-        mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub);
         mHistoryViewStub = (ViewStub) findViewById(R.id.history_view_stub);
         mScrimViews = new SystemBarScrimViews(this);
         getWindow().getAttributes().privateFlags |=
@@ -456,7 +441,10 @@
         // Reset some states
         mIgnoreAltTabRelease = false;
         if (mHistoryView != null) {
-            EventBus.getDefault().send(new HideHistoryEvent(false /* animate */));
+            ReferenceCountedTrigger t = new ReferenceCountedTrigger(this);
+            t.increment();
+            EventBus.getDefault().send(new HideHistoryEvent(false /* animate */, t));
+            t.decrement();
         }
 
         // Notify that recents is now hidden
@@ -515,6 +503,25 @@
     }
 
     @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putBoolean(KEY_SAVED_STATE_HISTORY_VISIBLE,
+                (mHistoryView != null) && mHistoryView.isVisible());
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+        if (savedInstanceState.getBoolean(KEY_SAVED_STATE_HISTORY_VISIBLE, false)) {
+            ReferenceCountedTrigger postHideStackAnimationTrigger =
+                    new ReferenceCountedTrigger(this);
+            postHideStackAnimationTrigger.increment();
+            EventBus.getDefault().send(new ShowHistoryEvent(postHideStackAnimationTrigger));
+            postHideStackAnimationTrigger.decrement();
+        }
+    }
+
+    @Override
     public void onTrimMemory(int level) {
         RecentsTaskLoader loader = Recents.getTaskLoader();
         if (loader != null) {
@@ -603,16 +610,18 @@
     }
 
     public final void onBusEvent(IterateRecentsEvent event) {
-        // Focus the next task
-        EventBus.getDefault().send(new FocusNextTaskViewEvent());
+        if (!dismissHistory()) {
+            // Focus the next task
+            EventBus.getDefault().send(new FocusNextTaskViewEvent());
 
-        // Start dozing after the recents button is clicked
-        RecentsDebugFlags debugFlags = Recents.getDebugFlags();
-        if (debugFlags.isFastToggleRecentsEnabled()) {
-            if (!mIterateTrigger.isDozing()) {
-                mIterateTrigger.startDozing();
-            } else {
-                mIterateTrigger.poke();
+            // Start dozing after the recents button is clicked
+            RecentsDebugFlags debugFlags = Recents.getDebugFlags();
+            if (debugFlags.isFastToggleRecentsEnabled()) {
+                if (!mIterateTrigger.isDozing()) {
+                    mIterateTrigger.startDozing();
+                } else {
+                    mIterateTrigger.poke();
+                }
             }
         }
     }
@@ -630,7 +639,7 @@
         } else if (event.triggeredFromHomeKey) {
             // Otherwise, dismiss Recents to Home
             if (mHistoryView != null && mHistoryView.isVisible()) {
-                ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
+                ReferenceCountedTrigger t = new ReferenceCountedTrigger(this);
                 t.increment();
                 t.addLastDecrementRunnable(new Runnable() {
                     @Override
@@ -651,7 +660,7 @@
 
     public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
         // Try and start the enter animation (or restart it on configuration changed)
-        ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
+        ReferenceCountedTrigger t = new ReferenceCountedTrigger(this);
         ViewAnimation.TaskViewEnterContext ctx = new ViewAnimation.TaskViewEnterContext(t);
         ctx.postAnimationTrigger.increment();
         if (mSearchWidgetInfo != null) {
@@ -724,8 +733,13 @@
     }
 
     public final void onBusEvent(AllTaskViewsDismissedEvent event) {
-        // Just go straight home (no animation necessary because there are no more task views)
-        dismissRecentsToHome(false /* animated */);
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (ssp.hasDockedTask()) {
+            mRecentsView.showEmptyView();
+        } else {
+            // Just go straight home (no animation necessary because there are no more task views)
+            dismissRecentsToHome(false /* animated */);
+        }
 
         // Keep track of all-deletions
         MetricsLogger.count(this, "overview_task_all_dismissed", 1);
@@ -769,13 +783,11 @@
             // provided.
             mHistoryView.setSystemInsets(mRecentsView.getSystemInsets());
         }
-        mHistoryView.show(mRecentsView.getTaskStack());
+        mHistoryView.show(mRecentsView.getTaskStack(), event.postHideStackAnimationTrigger);
     }
 
     public final void onBusEvent(HideHistoryEvent event) {
-        if (mHistoryView != null) {
-            mHistoryView.hide(event.animate, event.postAnimationTrigger);
-        }
+        mHistoryView.hide(event.animate, event.postHideHistoryAnimationTrigger);
     }
 
     private void refreshSearchWidgetView() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index e0bd59b..03b3788 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -28,7 +28,6 @@
 public class RecentsActivityLaunchState {
 
     public boolean launchedWithAltTab;
-    public boolean launchedWithNoRecentTasks;
     public boolean launchedFromAppWithThumbnail;
     public boolean launchedFromHome;
     public boolean launchedFromSearchHome;
@@ -49,28 +48,6 @@
         launchedViaDragGesture = false;
     }
 
-    /** Returns whether the status bar scrim should be animated when shown for the first time. */
-    public boolean shouldAnimateStatusBarScrim() {
-        return true;
-    }
-
-    /** Returns whether the status bar scrim should be visible. */
-    public boolean hasStatusBarScrim() {
-        return !launchedWithNoRecentTasks;
-    }
-
-    /** Returns whether the nav bar scrim should be animated when shown for the first time. */
-    public boolean shouldAnimateNavBarScrim() {
-        return true;
-    }
-
-    /** Returns whether the nav bar scrim should be visible. */
-    public boolean hasNavBarScrim() {
-        // Only show the scrim if we have recent tasks, and if the nav bar is not transposed
-        RecentsConfiguration config = Recents.getConfiguration();
-        return !launchedWithNoRecentTasks && !config.hasTransposedNavBar;
-    }
-
     /**
      * Returns the task to focus given the current launch state.
      */
@@ -103,13 +80,4 @@
             return -1;
         }
     }
-
-    @Override
-    public String toString() {
-        return "RecentsActivityLaunchState altTab: " + launchedWithAltTab +
-                ", noTasks: " + launchedWithNoRecentTasks +
-                ", fromHome: " + launchedFromHome +
-                ", fromSearchHome: " + launchedFromSearchHome +
-                ", reuse: " + launchedReuseTaskStackViews;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
index 34c35a7..3412852 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
@@ -25,14 +25,14 @@
 public class HideHistoryEvent extends EventBus.Event {
 
     public final boolean animate;
-    public final ReferenceCountedTrigger postAnimationTrigger;
+    public final ReferenceCountedTrigger postHideHistoryAnimationTrigger;
 
-    public HideHistoryEvent(boolean animate) {
-        this(animate, null);
-    }
-
-    public HideHistoryEvent(boolean animate, ReferenceCountedTrigger postAnimationTrigger) {
+    /**
+     * @param postHideHistoryAnimationTrigger the trigger that gets called when all the history animations are finished
+     *                                        when transitioning from the history view
+     */
+    public HideHistoryEvent(boolean animate, ReferenceCountedTrigger postHideHistoryAnimationTrigger) {
         this.animate = animate;
-        this.postAnimationTrigger = postAnimationTrigger;
+        this.postHideHistoryAnimationTrigger = postHideHistoryAnimationTrigger;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
index 870119d..c91752e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
@@ -17,10 +17,20 @@
 package com.android.systemui.recents.events.activity;
 
 import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 
 /**
  * This is sent when the history view button is clicked.
  */
 public class ShowHistoryEvent extends EventBus.Event {
-    // Simple event
+
+    public final ReferenceCountedTrigger postHideStackAnimationTrigger;
+
+    /**
+     * @param postHideStackAnimationTrigger the trigger that gets called when all the task animations are finished when
+     *                                      transitioning to the history view
+     */
+    public ShowHistoryEvent(ReferenceCountedTrigger postHideStackAnimationTrigger) {
+        this.postHideStackAnimationTrigger = postHideStackAnimationTrigger;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
index 2eee1da..06265bd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
@@ -110,7 +110,9 @@
         }
     }
 
+    private Context mContext;
     private LayoutInflater mLayoutInflater;
+    private final List<Task> mTasks = new ArrayList<>();
     private final List<Row> mRows = new ArrayList<>();
 
     public RecentsHistoryAdapter(Context context) {
@@ -121,6 +123,10 @@
      * Updates this adapter with the given tasks.
      */
     public void updateTasks(Context context, List<Task> tasks) {
+        mContext = context;
+        mTasks.clear();
+        mTasks.addAll(tasks);
+
         final Locale l = context.getResources().getConfiguration().locale;
         final String dateFormatStr = DateFormat.getBestDateTimePattern(l, "EEEEMMMMd");
         final List<Task> tasksMostRecent = new ArrayList<>(tasks);
@@ -144,6 +150,24 @@
         notifyDataSetChanged();
     }
 
+    /**
+     * Removes historical tasks beloning to the specified package and user.
+     */
+    public void removeTasks(String packageName, int userId) {
+        boolean packagesRemoved = false;
+        for (int i = mTasks.size() - 1; i >= 0; i--) {
+            Task task = mTasks.get(i);
+            String taskPackage = task.key.getComponent().getPackageName();
+            if (task.key.userId == userId && taskPackage.equals(packageName)) {
+                mTasks.remove(i);
+                packagesRemoved = true;
+            }
+        }
+        if (packagesRemoved) {
+            updateTasks(mContext, new ArrayList<Task>(mTasks));
+        }
+    }
+
     @Override
     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         switch (viewType) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
index 5851111..1163f14 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recents.history;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Rect;
@@ -29,9 +30,18 @@
 import android.widget.LinearLayout;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.PackagesChangedEvent;
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.views.TaskView;
+
+import java.util.ArrayList;
+import java.util.HashSet;
 
 /**
  * A list of the recent tasks that are not in the stack.
@@ -77,17 +87,21 @@
     /**
      * Updates this history view with the recent tasks, and then shows it.
      */
-    public void show(TaskStack stack) {
+    public void show(TaskStack stack, ReferenceCountedTrigger postHideAnimationTrigger) {
         setVisibility(View.VISIBLE);
         setAlpha(0f);
-        animate()
-                .alpha(1f)
-                .setDuration(mHistoryTransitionDuration)
-                .setInterpolator(mFastOutSlowInInterpolator)
-                .withLayer()
-                .start();
-
-        mAdapter.updateTasks(getContext(), stack.computeAllTasksList());
+        postHideAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+            @Override
+            public void run() {
+                animate()
+                        .alpha(1f)
+                        .setDuration(mHistoryTransitionDuration)
+                        .setInterpolator(mFastOutSlowInInterpolator)
+                        .withLayer()
+                        .start();
+            }
+        });
+        mAdapter.updateTasks(getContext(), stack.getHistoricalTasks());
         mIsVisible = true;
     }
 
@@ -165,8 +179,27 @@
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
+        super.onAttachedToWindow();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        EventBus.getDefault().unregister(this);
+    }
+
+    @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
         setSystemInsets(insets.getSystemWindowInsets());
         return insets;
     }
+
+    /**** EventBus Events ****/
+
+    public final void onBusEvent(PackagesChangedEvent event) {
+        mAdapter.removeTasks(event.packageName, event.userId);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
index 401b448..b06539a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
@@ -51,6 +51,10 @@
         }
     };
 
+    public ReferenceCountedTrigger(Context context) {
+        this(context, null, null, null);
+    }
+
     public ReferenceCountedTrigger(Context context, Runnable firstIncRunnable,
                                    Runnable lastDecRunnable, Runnable errorRunanable) {
         mContext = context;
@@ -97,7 +101,7 @@
             if (mErrorRunnable != null) {
                 mErrorRunnable.run();
             } else {
-                Log.e(TAG, "Invalid ref count");
+                throw new RuntimeException("Invalid ref count");
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 36acc28..addcc85 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -32,8 +32,8 @@
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
-
 import com.android.internal.logging.MetricsLogger;
+import android.widget.TextView;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsActivity;
@@ -55,6 +55,7 @@
 import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
+import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
@@ -75,31 +76,29 @@
     private static final String TAG = "RecentsView";
     private static final boolean DEBUG = false;
 
-    Handler mHandler;
+    private final Handler mHandler;
 
-    TaskStack mStack;
-    TaskStackView mTaskStackView;
-    RecentsAppWidgetHostView mSearchBar;
-    View mHistoryButton;
-    boolean mAwaitingFirstLayout = true;
-    boolean mLastTaskLaunchedWasFreeform;
+    private TaskStack mStack;
+    private TaskStackView mTaskStackView;
+    private RecentsAppWidgetHostView mSearchBar;
+    private TextView mHistoryButton;
+    private View mEmptyView;
+    private boolean mAwaitingFirstLayout = true;
+    private boolean mLastTaskLaunchedWasFreeform;
+    private Rect mSystemInsets = new Rect();
 
-    RecentsTransitionHelper mTransitionHelper;
-    RecentsViewTouchHandler mTouchHandler;
-    TaskStack.DockState[] mVisibleDockStates = {
+    private RecentsTransitionHelper mTransitionHelper;
+    private RecentsViewTouchHandler mTouchHandler;
+    private TaskStack.DockState[] mVisibleDockStates = {
             TaskStack.DockState.LEFT,
             TaskStack.DockState.TOP,
             TaskStack.DockState.RIGHT,
             TaskStack.DockState.BOTTOM,
     };
 
-    private Interpolator mFastOutSlowInInterpolator;
-    private Interpolator mFastOutLinearInInterpolator;
-    private int mHistoryTransitionDuration;
-
-    Rect mSystemInsets = new Rect();
-
-    final FlingAnimationUtils mFlingAnimationUtils;
+    private final Interpolator mFastOutSlowInInterpolator;
+    private final Interpolator mFastOutLinearInInterpolator;
+    private final FlingAnimationUtils mFlingAnimationUtils;
 
     public RecentsView(Context context) {
         this(context, null);
@@ -123,26 +122,32 @@
                 com.android.internal.R.interpolator.fast_out_slow_in);
         mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.fast_out_linear_in);
-        mHistoryTransitionDuration = res.getInteger(R.integer.recents_history_transition_duration);
         mTouchHandler = new RecentsViewTouchHandler(this);
         mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
 
         LayoutInflater inflater = LayoutInflater.from(context);
-        mHistoryButton = inflater.inflate(R.layout.recents_history_button, this, false);
+        mHistoryButton = (TextView) inflater.inflate(R.layout.recents_history_button, this, false);
         mHistoryButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                EventBus.getDefault().send(new ShowHistoryEvent());
+                ReferenceCountedTrigger postHideStackAnimationTrigger = new ReferenceCountedTrigger(v.getContext());
+                postHideStackAnimationTrigger.increment();
+                EventBus.getDefault().send(new ShowHistoryEvent(postHideStackAnimationTrigger));
+                postHideStackAnimationTrigger.decrement();
             }
         });
+        addView(mHistoryButton);
+        mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
+        addView(mEmptyView);
     }
 
     /** Set/get the bsp root node */
     public void setTaskStack(TaskStack stack) {
         RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
         mStack = stack;
         // Disable reusing task stack views until the visibility bug is fixed. b/25998134
-        if (false && config.getLaunchState().launchedReuseTaskStackViews) {
+        if (false && launchState.launchedReuseTaskStackViews) {
             if (mTaskStackView != null) {
                 // If onRecentsHidden is not triggered, we need to the stack view again here
                 mTaskStackView.reset();
@@ -162,10 +167,12 @@
             mTaskStackView.setCallbacks(this);
             addView(mTaskStackView);
         }
-        if (indexOfChild(mHistoryButton) == -1) {
-            addView(mHistoryButton);
+
+        // Update the top level view's visibilities
+        if (stack.getStackTaskCount() > 0) {
+            hideEmptyView();
         } else {
-            mHistoryButton.bringToFront();
+            showEmptyView();
         }
 
         // Trigger a new layout
@@ -309,13 +316,33 @@
         return mSearchBar != null && !mSearchBar.isReinflateRequired();
     }
 
-    /** Sets the visibility of the search bar */
-    public void setSearchBarVisibility(int visibility) {
+    /**
+     * Hides the task stack and shows the empty view.
+     */
+    public void showEmptyView() {
+        if (!RecentsDebugFlags.Static.DisableSearchBar && (mSearchBar != null)) {
+            mSearchBar.setVisibility(View.INVISIBLE);
+        }
+        mTaskStackView.setVisibility(View.INVISIBLE);
+        mEmptyView.setVisibility(View.VISIBLE);
+        mEmptyView.bringToFront();
+        mHistoryButton.bringToFront();
+    }
+
+    /**
+     * Shows the task stack and hides the empty view.
+     */
+    public void hideEmptyView() {
+        mEmptyView.setVisibility(View.INVISIBLE);
+        mTaskStackView.setVisibility(View.VISIBLE);
+        if (!RecentsDebugFlags.Static.DisableSearchBar && (mSearchBar != null)) {
+            mSearchBar.setVisibility(View.VISIBLE);
+        }
+        mTaskStackView.bringToFront();
         if (mSearchBar != null) {
-            mSearchBar.setVisibility(visibility);
-            // Always bring the search bar to the top
             mSearchBar.bringToFront();
         }
+        mHistoryButton.bringToFront();
     }
 
     /**
@@ -366,6 +393,10 @@
             mTaskStackView.measure(widthMeasureSpec, heightMeasureSpec);
         }
 
+        // Measure the empty view
+        measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+
         // Measure the history button with the full space above the stack, but width-constrained
         // to the stack
         Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
@@ -373,6 +404,7 @@
                 MeasureSpec.makeMeasureSpec(historyButtonRect.width(), MeasureSpec.EXACTLY),
                 MeasureSpec.makeMeasureSpec(historyButtonRect.height(),
                         MeasureSpec.EXACTLY));
+
         setMeasuredDimension(width, height);
     }
 
@@ -397,6 +429,9 @@
             mTaskStackView.layout(left, top, left + getMeasuredWidth(), top + getMeasuredHeight());
         }
 
+        // Layout the empty view
+        mEmptyView.layout(left, top, right, bottom);
+
         // Layout the history button left-aligned with the stack, but offset from the top of the
         // view
         Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
@@ -545,12 +580,21 @@
 
     public final void onBusEvent(ShowHistoryEvent event) {
         // Hide the history button when the history view is shown
-        hideHistoryButton(mHistoryTransitionDuration);
+        hideHistoryButton(getResources().getInteger(R.integer.recents_history_transition_duration),
+                event.postHideStackAnimationTrigger);
+        event.postHideStackAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+            @Override
+            public void run() {
+                setAlpha(0f);
+            }
+        });
     }
 
     public final void onBusEvent(HideHistoryEvent event) {
         // Show the history button when the history view is hidden
-        showHistoryButton(mHistoryTransitionDuration);
+        setAlpha(1f);
+        showHistoryButton(getResources().getInteger(R.integer.recents_history_transition_duration),
+                event.postHideHistoryAnimationTrigger);
     }
 
     public final void onBusEvent(ShowHistoryButtonEvent event) {
@@ -565,31 +609,57 @@
         RecentsDebugFlags debugFlags = Recents.getDebugFlags();
         if (!debugFlags.isHistoryEnabled()) {
             hideHistoryButton(100);
+        } else {
+            showHistoryButton(100);
         }
     }
 
     /**
      * Shows the history button.
      */
-    private void showHistoryButton(int duration) {
+    private void showHistoryButton(final int duration) {
+        ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger(getContext());
+        postAnimationTrigger.increment();
+        showHistoryButton(duration, postAnimationTrigger);
+        postAnimationTrigger.decrement();
+    }
+
+    private void showHistoryButton(final int duration,
+            final ReferenceCountedTrigger postHideHistoryAnimationTrigger) {
         RecentsDebugFlags debugFlags = Recents.getDebugFlags();
         if (!debugFlags.isHistoryEnabled()) {
             return;
         }
 
         mHistoryButton.setVisibility(View.VISIBLE);
-        mHistoryButton.animate()
-                .alpha(1f)
-                .setDuration(duration)
-                .setInterpolator(mFastOutSlowInInterpolator)
-                .withLayer()
-                .start();
+        mHistoryButton.setAlpha(0f);
+        mHistoryButton.setText(getContext().getString(R.string.recents_history_label_format,
+                mStack.getHistoricalTasks().size()));
+        postHideHistoryAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+            @Override
+            public void run() {
+                mHistoryButton.animate()
+                        .alpha(1f)
+                        .setDuration(duration)
+                        .setInterpolator(mFastOutSlowInInterpolator)
+                        .withLayer()
+                        .start();
+            }
+        });
     }
 
     /**
      * Hides the history button.
      */
     private void hideHistoryButton(int duration) {
+        ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger(getContext());
+        postAnimationTrigger.increment();
+        hideHistoryButton(duration, postAnimationTrigger);
+        postAnimationTrigger.decrement();
+    }
+
+    private void hideHistoryButton(int duration,
+            final ReferenceCountedTrigger postHideStackAnimationTrigger) {
         mHistoryButton.animate()
                 .alpha(0f)
                 .setDuration(duration)
@@ -598,10 +668,12 @@
                     @Override
                     public void run() {
                         mHistoryButton.setVisibility(View.INVISIBLE);
+                        postHideStackAnimationTrigger.decrement();
                     }
                 })
                 .withLayer()
                 .start();
+        postHideStackAnimationTrigger.increment();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 2920295..37a0194 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -189,7 +189,7 @@
             case MotionEvent.ACTION_CANCEL: {
                 if (mDragging) {
                     ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger(
-                            mRv.getContext(), null, null, null);
+                            mRv.getContext());
                     postAnimationTrigger.increment();
                     EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView,
                             mLastDropTarget, postAnimationTrigger));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 5a09ee4..f84eb53 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -62,13 +62,14 @@
      * Prepares the scrim views for animating when entering Recents. This will be called before
      * the first draw.
      */
-    public void prepareEnterRecentsAnimation() {
+    public void prepareEnterRecentsAnimation(boolean hasStatusBarScrim, boolean animateStatusBarScrim,
+            boolean hasNavBarScrim, boolean animateNavBarScrim) {
         RecentsConfiguration config = Recents.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
-        mHasNavBarScrim = launchState.hasNavBarScrim();
-        mShouldAnimateNavBarScrim = launchState.shouldAnimateNavBarScrim();
-        mHasStatusBarScrim = launchState.hasStatusBarScrim();
-        mShouldAnimateStatusBarScrim = launchState.shouldAnimateStatusBarScrim();
+        mHasNavBarScrim = hasStatusBarScrim;
+        mShouldAnimateStatusBarScrim = animateStatusBarScrim;
+        mHasStatusBarScrim = hasNavBarScrim;
+        mShouldAnimateNavBarScrim = animateNavBarScrim;
 
         mNavBarScrimView.setVisibility(mHasNavBarScrim && !mShouldAnimateNavBarScrim ?
                 View.VISIBLE : View.INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 350bc2b..404ac47 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -27,6 +27,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.GradientDrawable;
 import android.os.Bundle;
+import android.os.Parcelable;
 import android.util.IntProperty;
 import android.util.Log;
 import android.util.Property;
@@ -91,6 +92,12 @@
     private final static String TAG = "TaskStackView";
     private final static boolean DEBUG = false;
 
+    private final static String KEY_SAVED_STATE_SUPER = "saved_instance_state_super";
+    private final static String KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE =
+            "saved_instance_state_layout_focused_state";
+    private final static String KEY_SAVED_STATE_LAYOUT_STACK_SCROLL =
+            "saved_instance_state_layout_stack_scroll";
+
     // The thresholds at which to show/hide the history button.
     private static final float SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
     private static final float HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
@@ -828,6 +835,24 @@
     }
 
     @Override
+    protected Parcelable onSaveInstanceState() {
+        Bundle savedState = new Bundle();
+        savedState.putParcelable(KEY_SAVED_STATE_SUPER, super.onSaveInstanceState());
+        savedState.putFloat(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE, mLayoutAlgorithm.getFocusState());
+        savedState.putFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL, mStackScroller.getStackScroll());
+        return super.onSaveInstanceState();
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        Bundle savedState = (Bundle) state;
+        super.onRestoreInstanceState(savedState.getParcelable(KEY_SAVED_STATE_SUPER));
+
+        mLayoutAlgorithm.setFocusState(savedState.getFloat(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE));
+        mStackScroller.setStackScroll(savedState.getFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL));
+    }
+
+    @Override
     public CharSequence getAccessibilityClassName() {
         return TaskStackView.class.getName();
     }
@@ -1040,8 +1065,11 @@
         }
 
         // Update the history button visibility
-        if (mStackScroller.getStackScroll() < SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
+        if (shouldShowHistoryButton() &&
+                mStackScroller.getStackScroll() < SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
             EventBus.getDefault().send(new ShowHistoryButtonEvent());
+        } else {
+            EventBus.getDefault().send(new HideHistoryButtonEvent());
         }
 
         // Start dozing
@@ -1370,7 +1398,8 @@
         requestSynchronizeStackViewsWithModel();
         postInvalidateOnAnimation();
 
-        if (prevScroll > SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD &&
+        if (shouldShowHistoryButton() &&
+                prevScroll > SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD &&
                 curScroll <= SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
             EventBus.getDefault().send(new ShowHistoryButtonEvent());
         } else if (prevScroll < HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD &&
@@ -1537,32 +1566,47 @@
     }
 
     public final void onBusEvent(ShowHistoryEvent event) {
+        // The history view's animation will be deferred until all the stack task views are animated
+        // away
+        int historyTransitionDuration =
+                getResources().getInteger(R.integer.recents_history_transition_duration);
         List<TaskView> taskViews = getTaskViews();
         int taskViewCount = taskViews.size();
         for (int i = taskViewCount - 1; i >= 0; i--) {
             TaskView tv = taskViews.get(i);
             tv.animate()
                     .alpha(0f)
-                    .setDuration(200)
+                    .setDuration(historyTransitionDuration)
                     .setUpdateListener(null)
                     .setListener(null)
                     .withLayer()
+                    .withEndAction(event.postHideStackAnimationTrigger.decrementAsRunnable())
                     .start();
+            event.postHideStackAnimationTrigger.increment();
         }
     }
 
     public final void onBusEvent(HideHistoryEvent event) {
+        // The stack task view animations will be deferred until the history view has been animated
+        // away
+        final int historyTransitionDuration =
+                getResources().getInteger(R.integer.recents_history_transition_duration);
         List<TaskView> taskViews = getTaskViews();
         int taskViewCount = taskViews.size();
         for (int i = taskViewCount - 1; i >= 0; i--) {
-            TaskView tv = taskViews.get(i);
-            tv.animate()
-                    .alpha(1f)
-                    .setDuration(200)
-                    .setUpdateListener(null)
-                    .setListener(null)
-                    .withLayer()
-                    .start();
+            final TaskView tv = taskViews.get(i);
+            event.postHideHistoryAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+                @Override
+                public void run() {
+                    tv.animate()
+                            .alpha(1f)
+                            .setDuration(historyTransitionDuration)
+                            .setUpdateListener(null)
+                            .setListener(null)
+                            .withLayer()
+                            .start();
+                }
+            });
         }
     }
 
@@ -1626,4 +1670,11 @@
         }
         return -1;
     }
+
+    /**
+     * @return whether the history button should be visible
+     */
+    private boolean shouldShowHistoryButton() {
+        return !mStack.getHistoricalTasks().isEmpty();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 93264ff..c01f170 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -30,6 +30,7 @@
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.MotionEvent;
+import android.view.PointerIcon;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.View.OnTouchListener;
@@ -118,8 +119,8 @@
         updateDisplayInfo();
         boolean landscape = getResources().getConfiguration().orientation
                 == Configuration.ORIENTATION_LANDSCAPE;
-        mHandle.setPointerShape(
-                landscape ? STYLE_HORIZONTAL_DOUBLE_ARROW : STYLE_VERTICAL_DOUBLE_ARROW);
+        mHandle.setPointerIcon(PointerIcon.getSystemIcon(getContext(),
+                landscape ? STYLE_HORIZONTAL_DOUBLE_ARROW : STYLE_VERTICAL_DOUBLE_ARROW));
         getViewTreeObserver().addOnComputeInternalInsetsListener(this);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index da19b06..9d4ec10 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -128,6 +128,7 @@
     private boolean mPendingRecheckAll;
     private long mCollapseTime;
     private boolean mHovering = false;
+    private int mLastActiveStream;
 
     public VolumeDialog(Context context, int windowType, VolumeDialogController controller,
             ZenModeController zenModeController, Callback callback) {
@@ -283,10 +284,14 @@
             @Override
             public void onLayoutChange(View v, int left, int top, int right, int bottom,
                     int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                final boolean moved = oldLeft != left || oldTop != top;
+                final boolean moved = mLastActiveStream != mActiveStream ||
+                        oldLeft != left || oldTop != top;
                 if (D.BUG) Log.d(TAG, "onLayoutChange moved=" + moved
                         + " old=" + new Rect(oldLeft, oldTop, oldRight, oldBottom).toShortString()
-                        + " new=" + new Rect(left,top,right,bottom).toShortString());
+                        + "," + mLastActiveStream
+                        + " new=" + new Rect(left,top,right,bottom).toShortString()
+                        + "," + mActiveStream);
+                mLastActiveStream = mActiveStream;
                 if (moved) {
                     for (int i = 0; i < mDialogContentView.getChildCount(); i++) {
                         final View c = mDialogContentView.getChildAt(i);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ed64c2b..65a27c8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -255,11 +255,6 @@
     private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9;
 
     /**
-     * used internally to send a sticky broadcast delayed.
-     */
-    private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = 11;
-
-    /**
      * PAC manager has received new port.
      */
     private static final int EVENT_PROXY_HAS_CHANGED = 16;
@@ -2515,11 +2510,6 @@
                     handleDeprecatedGlobalHttpProxy();
                     break;
                 }
-                case EVENT_SEND_STICKY_BROADCAST_INTENT: {
-                    Intent intent = (Intent)msg.obj;
-                    sendStickyBroadcast(intent);
-                    break;
-                }
                 case EVENT_PROXY_HAS_CHANGED: {
                     handleApplyDefaultProxy((ProxyInfo)msg.obj);
                     break;
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index ef79cfe..04abcca 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -166,6 +166,7 @@
     static final int MSG_SET_ACTIVE = 3020;
     static final int MSG_SET_INTERACTIVE = 3030;
     static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 3040;
+    static final int MSG_SWITCH_IME = 3050;
 
     static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
 
@@ -2851,6 +2852,9 @@
             case MSG_SET_INTERACTIVE:
                 handleSetInteractive(msg.arg1 != 0);
                 return true;
+            case MSG_SWITCH_IME:
+                handleSwitchInputMethod(msg.arg1 != 0);
+                return true;
             case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
                 final int sequenceNumber = msg.arg1;
                 final ClientState clientState = (ClientState)msg.obj;
@@ -2887,6 +2891,18 @@
         }
     }
 
+    private void handleSwitchInputMethod(final boolean forwardDirection) {
+        synchronized (mMethodMap) {
+            // TODO: Support forwardDirection.
+            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
+                    false, mMethodMap.get(mCurMethodId), mCurrentSubtype);
+            if (nextSubtype == null) {
+                return;
+            }
+            setInputMethodLocked(nextSubtype.mImi.getId(), nextSubtype.mSubtypeId);
+        }
+    }
+
     private boolean chooseNewDefaultIMELocked() {
         final InputMethodInfo imi = InputMethodUtils.getMostApplicableDefaultIME(
                 mSettings.getEnabledInputMethodListLocked());
@@ -3734,6 +3750,13 @@
             mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_INTERACTIVE,
                     interactive ? 1 : 0, 0));
         }
+
+        @Override
+        public void switchInputMethod(boolean forwardDirection) {
+            // Do everything in handler so as not to block the caller.
+            mHandler.sendMessage(mHandler.obtainMessage(MSG_SWITCH_IME,
+                    forwardDirection ? 1 : 0, 0));
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 033a4b8..1a21f5c 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -356,6 +356,10 @@
             }
         }
 
+        if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) {
+            key = Settings.Secure.LOCK_PATTERN_ENABLED;
+        }
+
         return mStorage.readKeyValue(key, defaultValue, userId);
     }
 
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 502d61a..ca5212a 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2449,7 +2449,7 @@
             if (sessionBundle != null) {
                 String accountType = sessionBundle.getString(AccountManager.KEY_ACCOUNT_TYPE);
                 if (TextUtils.isEmpty(accountType)
-                        && !mAccountType.equalsIgnoreCase(mAccountType)) {
+                        || !mAccountType.equalsIgnoreCase(accountType)) {
                     Log.w(TAG, "Account type in session bundle doesn't match request.");
                 }
                 // Add accountType info to session bundle. This will
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 119f42d..e1bc580 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -29,6 +29,7 @@
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
+import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
@@ -1547,7 +1548,7 @@
             // to ensure that it is safe to do so.  If the upcoming activity will also
             // be part of the voice session, we can only launch it if it has explicitly
             // said it supports the VOICE category, or it is a part of the calling app.
-            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
+            if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
                     && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
                 try {
                     intent.addCategory(Intent.CATEGORY_VOICE);
@@ -1594,63 +1595,9 @@
             return err;
         }
 
-        boolean abort = false;
-
-        final int startAnyPerm = mService.checkPermission(
-                START_ANY_ACTIVITY, callingPid, callingUid);
-
-        if (startAnyPerm != PERMISSION_GRANTED) {
-            final int componentRestriction = getComponentRestrictionForCallingPackage(
-                    aInfo, callingPackage, callingPid, callingUid, ignoreTargetSecurity);
-            final int actionRestriction = getActionRestrictionForCallingPackage(
-                    intent.getAction(), callingPackage, callingPid, callingUid);
-
-            if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION
-                    || actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
-                if (resultRecord != null) {
-                    resultStack.sendActivityResultLocked(-1,
-                            resultRecord, resultWho, requestCode,
-                            Activity.RESULT_CANCELED, null);
-                }
-                String msg;
-                if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
-                    msg = "Permission Denial: starting " + intent.toString()
-                            + " from " + callerApp + " (pid=" + callingPid
-                            + ", uid=" + callingUid + ")" + " with revoked permission "
-                            + ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction());
-                } else if (!aInfo.exported) {
-                    msg = "Permission Denial: starting " + intent.toString()
-                            + " from " + callerApp + " (pid=" + callingPid
-                            + ", uid=" + callingUid + ")"
-                            + " not exported from uid " + aInfo.applicationInfo.uid;
-                } else {
-                    msg = "Permission Denial: starting " + intent.toString()
-                            + " from " + callerApp + " (pid=" + callingPid
-                            + ", uid=" + callingUid + ")"
-                            + " requires " + aInfo.permission;
-                }
-                Slog.w(TAG, msg);
-                throw new SecurityException(msg);
-            }
-
-            if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) {
-                String message = "Appop Denial: starting " + intent.toString()
-                        + " from " + callerApp + " (pid=" + callingPid
-                        + ", uid=" + callingUid + ")"
-                        + " requires " + AppOpsManager.permissionToOp(
-                                ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction()));
-                Slog.w(TAG, message);
-                abort = true;
-            } else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) {
-                String message = "Appop Denial: starting " + intent.toString()
-                        + " from " + callerApp + " (pid=" + callingPid
-                        + ", uid=" + callingUid + ")"
-                        + " requires appop " + AppOpsManager.permissionToOp(aInfo.permission);
-                Slog.w(TAG, message);
-                abort = true;
-            }
-        }
-
+        boolean abort = !checkStartAnyActivityPermission(intent, aInfo, resultWho, requestCode,
+                callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
+                resultRecord, resultStack);
         abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                 callingPid, resolvedType, aInfo.applicationInfo);
 
@@ -1679,21 +1626,23 @@
                     PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
                             | PendingIntent.FLAG_IMMUTABLE, null);
             int flags = intent.getFlags();
-            intent = km.createConfirmDeviceCredentialIntent(null, null);
-            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
-            intent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
-            intent.putExtra(Intent.EXTRA_USER_ID, userId);
-            intent.setFlags(flags);
+            Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, user.id);
+            if (newIntent != null) {
+                intent = newIntent;
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+                intent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
+                intent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
+                intent.setFlags(flags);
 
-            resolvedType = null;
-            callingUid = realCallingUid;
-            callingPid = realCallingPid;
+                resolvedType = null;
+                callingUid = realCallingUid;
+                callingPid = realCallingPid;
 
-            UserInfo parent = UserManager.get(mService.mContext).getProfileParent(userId);
-            aInfo = resolveActivity(intent, null, PackageManager.MATCH_DEFAULT_ONLY
-                    | ActivityManagerService.STOCK_PM_FLAGS, null, parent.id);
+                UserInfo parent = UserManager.get(mService.mContext).getProfileParent(userId);
+                aInfo = resolveActivity(intent, null, PackageManager.MATCH_DEFAULT_ONLY
+                        | ActivityManagerService.STOCK_PM_FLAGS, null, parent.id);
+            }
         }
 
         if (abort) {
@@ -1799,6 +1748,66 @@
         return err;
     }
 
+    private boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo,
+            String resultWho, int requestCode, int callingPid, int callingUid,
+            String callingPackage, boolean ignoreTargetSecurity, ProcessRecord callerApp,
+            ActivityRecord resultRecord, ActivityStack resultStack) {
+        final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid,
+                callingUid);
+        if (startAnyPerm ==  PERMISSION_GRANTED) {
+            return true;
+        }
+        final int componentRestriction = getComponentRestrictionForCallingPackage(
+                aInfo, callingPackage, callingPid, callingUid, ignoreTargetSecurity);
+        final int actionRestriction = getActionRestrictionForCallingPackage(
+                intent.getAction(), callingPackage, callingPid, callingUid);
+        if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION
+                || actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
+            if (resultRecord != null) {
+                resultStack.sendActivityResultLocked(-1,
+                        resultRecord, resultWho, requestCode,
+                        Activity.RESULT_CANCELED, null);
+            }
+            final String msg;
+            if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
+                msg = "Permission Denial: starting " + intent.toString()
+                        + " from " + callerApp + " (pid=" + callingPid
+                        + ", uid=" + callingUid + ")" + " with revoked permission "
+                        + ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction());
+            } else if (!aInfo.exported) {
+                msg = "Permission Denial: starting " + intent.toString()
+                        + " from " + callerApp + " (pid=" + callingPid
+                        + ", uid=" + callingUid + ")"
+                        + " not exported from uid " + aInfo.applicationInfo.uid;
+            } else {
+                msg = "Permission Denial: starting " + intent.toString()
+                        + " from " + callerApp + " (pid=" + callingPid
+                        + ", uid=" + callingUid + ")"
+                        + " requires " + aInfo.permission;
+            }
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+
+        if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) {
+            final String message = "Appop Denial: starting " + intent.toString()
+                    + " from " + callerApp + " (pid=" + callingPid
+                    + ", uid=" + callingUid + ")"
+                    + " requires " + AppOpsManager.permissionToOp(
+                            ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction()));
+            Slog.w(TAG, message);
+            return false;
+        } else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) {
+            final String message = "Appop Denial: starting " + intent.toString()
+                    + " from " + callerApp + " (pid=" + callingPid
+                    + ", uid=" + callingUid + ")"
+                    + " requires appop " + AppOpsManager.permissionToOp(aInfo.permission);
+            Slog.w(TAG, message);
+            return false;
+        }
+        return true;
+    }
+
     private UserInfo getUserInfo(int userId) {
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -1877,7 +1886,7 @@
         return ACTIVITY_RESTRICTION_NONE;
     }
 
-    ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds) {
+    private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds) {
         final TaskRecord task = r.task;
 
         if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
@@ -1992,7 +2001,7 @@
             Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
                     "\"singleInstance\" or \"singleTask\"");
             launchFlags &=
-                    ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+                    ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
         } else {
             switch (r.info.documentLaunchMode) {
                 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
@@ -2004,7 +2013,7 @@
                     launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
                     break;
                 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
-                    launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+                    launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
                     break;
             }
         }
@@ -2013,7 +2022,7 @@
                 && !launchSingleTask && !launchSingleInstance
                 && (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
 
-        if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0
+        if (r.resultTo != null && (launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
                 && r.resultTo.task.stack != null) {
             // For whatever reason this activity is being launched into a new
             // task...  yet the caller has requested a result back.  Well, that
@@ -2028,15 +2037,15 @@
         }
 
         if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
-            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+            launchFlags |= FLAG_ACTIVITY_NEW_TASK;
         }
 
         // If we are actually going to launch in to a new task, there are some cases where
         // we further want to do multiple task.
-        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+        if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
             if (launchTaskBehind
                     || r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) {
-                launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+                launchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
             }
         }
 
@@ -2105,8 +2114,8 @@
             // If task is empty, then adopt the interesting intent launch flags in to the
             // activity being started.
             if (root == null) {
-                final int flagsOfInterest = Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT
+                final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK
+                        | FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT
                         | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
                 launchFlags = (launchFlags&~flagsOfInterest)
                         | (baseIntent.getFlags()&flagsOfInterest);
@@ -2117,7 +2126,7 @@
             // If the task is not empty and the caller is asking to start it as the root
             // of a new task, then we don't actually want to start this on the task.  We
             // will bring the task to the front, and possibly give it a new intent.
-            } else if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+            } else if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
                 addingToTask = false;
 
             } else {
@@ -2141,20 +2150,20 @@
             if (sourceRecord == null) {
                 // This activity is not being started from another...  in this
                 // case we -always- start a new task.
-                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
+                if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
                     Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
                             "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
-                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+                    launchFlags |= FLAG_ACTIVITY_NEW_TASK;
                 }
             } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                 // The original activity who is starting us is running as a single
                 // instance...  this new activity it is starting must go on its
                 // own task.
-                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+                launchFlags |= FLAG_ACTIVITY_NEW_TASK;
             } else if (launchSingleInstance || launchSingleTask) {
                 // The activity being started is a single instance...  it always
                 // gets launched into its own task.
-                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+                launchFlags |= FLAG_ACTIVITY_NEW_TASK;
             }
         }
 
@@ -2168,10 +2177,10 @@
                 // so we don't want to blindly throw it in to that task.  Instead we will take
                 // the NEW_TASK flow and try to find a task for it. But save the task information
                 // so it can be used when creating the new task.
-                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
+                if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
                     Slog.w(TAG, "startActivity called from finishing " + sourceRecord
                             + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
-                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+                    launchFlags |= FLAG_ACTIVITY_NEW_TASK;
                     newTaskInfo = sourceRecord.info;
                     newTaskIntent = sourceRecord.task.intent;
                 }
@@ -2190,216 +2199,192 @@
         intent.setFlags(launchFlags);
         final boolean noAnimation = (launchFlags & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0;
 
-        // We may want to try to place the new activity in to an existing task.  We always
-        // do this if the target activity is singleTask or singleInstance; we will also do
-        // this if NEW_TASK has been requested, and there is not an additional qualifier telling
-        // us to still place it in a new task: multi task, always doc mode, or being asked to
-        // launch this as a new task behind the current one.
-        if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
-                (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
-                || launchSingleInstance || launchSingleTask) {
-            // If bring to front is requested, and no result is requested and we have not
-            // been given an explicit task to launch in to, and
-            // we can find a task that was started with this same
-            // component, then instead of launching bring that one to the front.
-            if (inTask == null && r.resultTo == null) {
-                // See if there is a task to bring to the front.  If this is
-                // a SINGLE_INSTANCE activity, there can be one and only one
-                // instance of it in the history, and it is always in its own
-                // unique task, so we do a special search.
-                ActivityRecord intentActivity = !launchSingleInstance ?
-                        findTaskLocked(r) : findActivityLocked(intent, r.info);
-                if (intentActivity != null) {
-                    // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused
-                    // but still needs to be a lock task mode violation since the task gets
-                    // cleared out and the device would otherwise leave the locked task.
-                    if (isLockTaskModeViolation(intentActivity.task,
-                            (launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
-                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
-                        showLockTaskToast();
-                        Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
-                        return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
+        ActivityRecord intentActivity = getReusableIntentActivity(r, inTask, intent,
+                launchSingleInstance, launchSingleTask, launchFlags);
+        if (intentActivity != null) {
+            // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused
+            // but still needs to be a lock task mode violation since the task gets
+            // cleared out and the device would otherwise leave the locked task.
+            if (isLockTaskModeViolation(intentActivity.task,
+                    (launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
+                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
+                showLockTaskToast();
+                Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
+                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
+            }
+            if (r.task == null) {
+                r.task = intentActivity.task;
+            }
+            if (intentActivity.task.intent == null) {
+                // This task was started because of movement of the activity based on affinity...
+                // Now that we are actually launching it, we can assign the base intent.
+                intentActivity.task.setIntent(r);
+            }
+            targetStack = intentActivity.task.stack;
+            targetStack.mLastPausedActivity = null;
+            // If the target task is not in the front, then we need
+            // to bring it to the front...  except...  well, with
+            // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
+            // to have the same behavior as if a new instance was
+            // being started, which means not bringing it to the front
+            // if the caller is not itself in the front.
+            final ActivityStack focusStack = getFocusedStack();
+            ActivityRecord curTop = (focusStack == null)
+                    ? null : focusStack.topRunningNonDelayedActivityLocked(notTop);
+            boolean movedToFront = false;
+            if (curTop != null && (curTop.task != intentActivity.task ||
+                    curTop.task != focusStack.topTask())) {
+                r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
+                if (sourceRecord == null || (sourceStack.topActivity() != null &&
+                        sourceStack.topActivity().task == sourceRecord.task)) {
+                    // We really do want to push this one into the user's face, right now.
+                    if (launchTaskBehind && sourceRecord != null) {
+                        intentActivity.setTaskToAffiliateWith(sourceRecord.task);
                     }
-                    if (r.task == null) {
-                        r.task = intentActivity.task;
+                    movedHome = true;
+                    targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation,
+                            options, r.appTimeTracker, "bringingFoundTaskToFront");
+                    movedToFront = true;
+                    if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
+                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
+                        // Caller wants to appear on home activity.
+                        intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
                     }
-                    if (intentActivity.task.intent == null) {
-                        // This task was started because of movement of
-                        // the activity based on affinity...  now that we
-                        // are actually launching it, we can assign the
-                        // base intent.
-                        intentActivity.task.setIntent(r);
-                    }
-                    targetStack = intentActivity.task.stack;
-                    targetStack.mLastPausedActivity = null;
-                    // If the target task is not in the front, then we need
-                    // to bring it to the front...  except...  well, with
-                    // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
-                    // to have the same behavior as if a new instance was
-                    // being started, which means not bringing it to the front
-                    // if the caller is not itself in the front.
-                    final ActivityStack focusStack = getFocusedStack();
-                    ActivityRecord curTop = (focusStack == null)
-                            ? null : focusStack.topRunningNonDelayedActivityLocked(notTop);
-                    boolean movedToFront = false;
-                    if (curTop != null && (curTop.task != intentActivity.task ||
-                            curTop.task != focusStack.topTask())) {
-                        r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
-                        if (sourceRecord == null || (sourceStack.topActivity() != null &&
-                                sourceStack.topActivity().task == sourceRecord.task)) {
-                            // We really do want to push this one into the user's face, right now.
-                            if (launchTaskBehind && sourceRecord != null) {
-                                intentActivity.setTaskToAffiliateWith(sourceRecord.task);
-                            }
-                            movedHome = true;
-                            targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation,
-                                    options, r.appTimeTracker, "bringingFoundTaskToFront");
-                            movedToFront = true;
-                            if ((launchFlags &
-                                    (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
-                                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
-                                // Caller wants to appear on home activity.
-                                intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
-                            }
-                            options = null;
-                        }
-                    }
-                    if (!movedToFront && doResume) {
-                        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + targetStack
-                                + " from " + intentActivity);
-                        targetStack.moveToFront("intentActivityFound");
-                    }
-
-                    // If the caller has requested that the target task be
-                    // reset, then do so.
-                    if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
-                        intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
-                    }
-                    if ((startFlags & ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
-                        // We don't need to start a new activity, and
-                        // the client said not to do anything if that
-                        // is the case, so this is it!  And for paranoia, make
-                        // sure we have correctly resumed the top activity.
-                        if (doResume) {
-                            resumeTopActivitiesLocked(targetStack, null, options);
-
-                            // Make sure to notify Keyguard as well if we are not running an app
-                            // transition later.
-                            if (!movedToFront) {
-                                notifyActivityDrawnForKeyguard();
-                            }
-                        } else {
-                            ActivityOptions.abort(options);
-                        }
-                        updateUserStackLocked(r.userId, targetStack);
-                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
-                    }
-                    if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
-                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
-                        // The caller has requested to completely replace any
-                        // existing task with its new activity.  Well that should
-                        // not be too hard...
-                        reuseTask = intentActivity.task;
-                        reuseTask.performClearTaskLocked();
-                        reuseTask.setIntent(r);
-                    } else if ((launchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
-                            || launchSingleInstance || launchSingleTask) {
-                        // In this situation we want to remove all activities
-                        // from the task up to the one being started.  In most
-                        // cases this means we are resetting the task to its
-                        // initial state.
-                        ActivityRecord top =
-                                intentActivity.task.performClearTaskLocked(r, launchFlags);
-                        if (top != null) {
-                            if (top.frontOfTask) {
-                                // Activity aliases may mean we use different
-                                // intents for the top activity, so make sure
-                                // the task now has the identity of the new
-                                // intent.
-                                top.task.setIntent(r);
-                            }
-                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
-                                    r, top.task);
-                            top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
-                        } else {
-                            // A special case: we need to start the activity because it is not
-                            // currently running, and the caller has asked to clear the current
-                            // task to have this activity at the top.
-                            addingToTask = true;
-                            // Now pretend like this activity is being started by the top of its
-                            // task, so it is put in the right place.
-                            sourceRecord = intentActivity;
-                            TaskRecord task = sourceRecord.task;
-                            if (task != null && task.stack == null) {
-                                // Target stack got cleared when we all activities were removed
-                                // above. Go ahead and reset it.
-                                targetStack = computeStackFocus(
-                                        sourceRecord, false /* newTask */, null /* bounds */);
-                                targetStack.addTask(task,
-                                        !launchTaskBehind /* toTop */, "startActivityUnchecked");
-                            }
-
-                        }
-                    } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
-                        // In this case the top activity on the task is the
-                        // same as the one being launched, so we take that
-                        // as a request to bring the task to the foreground.
-                        // If the top activity in the task is the root
-                        // activity, deliver this new intent to it if it
-                        // desires.
-                        if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || launchSingleTop)
-                                && intentActivity.realActivity.equals(r.realActivity)) {
-                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
-                                    intentActivity.task);
-                            if (intentActivity.frontOfTask) {
-                                intentActivity.task.setIntent(r);
-                            }
-                            intentActivity.deliverNewIntentLocked(callingUid, r.intent,
-                                    r.launchedFromPackage);
-                        } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
-                            // In this case we are launching the root activity
-                            // of the task, but with a different intent.  We
-                            // should start a new instance on top.
-                            addingToTask = true;
-                            sourceRecord = intentActivity;
-                        }
-                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
-                        // In this case an activity is being launched in to an
-                        // existing task, without resetting that task.  This
-                        // is typically the situation of launching an activity
-                        // from a notification or shortcut.  We want to place
-                        // the new activity on top of the current task.
-                        addingToTask = true;
-                        sourceRecord = intentActivity;
-                    } else if (!intentActivity.task.rootWasReset) {
-                        // In this case we are launching in to an existing task
-                        // that has not yet been started from its front door.
-                        // The current task has been brought to the front.
-                        // Ideally, we'd probably like to place this new task
-                        // at the bottom of its stack, but that's a little hard
-                        // to do with the current organization of the code so
-                        // for now we'll just drop it.
-                        intentActivity.task.setIntent(r);
-                    }
-                    if (!addingToTask && reuseTask == null) {
-                        // We didn't do anything...  but it was needed (a.k.a., client
-                        // don't use that intent!)  And for paranoia, make
-                        // sure we have correctly resumed the top activity.
-                        if (doResume) {
-                            targetStack.resumeTopActivityLocked(null, options);
-                            if (!movedToFront) {
-                                // Make sure to notify Keyguard as well if we are not running an app
-                                // transition later.
-                                notifyActivityDrawnForKeyguard();
-                            }
-                        } else {
-                            ActivityOptions.abort(options);
-                        }
-                        updateUserStackLocked(r.userId, targetStack);
-                        return ActivityManager.START_TASK_TO_FRONT;
-                    }
+                    options = null;
                 }
             }
+            if (!movedToFront && doResume) {
+                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + targetStack
+                        + " from " + intentActivity);
+                targetStack.moveToFront("intentActivityFound");
+            }
+
+            // If the caller has requested that the target task be
+            // reset, then do so.
+            if ((launchFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
+                intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
+            }
+            if ((startFlags & ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
+                // We don't need to start a new activity, and
+                // the client said not to do anything if that
+                // is the case, so this is it!  And for paranoia, make
+                // sure we have correctly resumed the top activity.
+                if (doResume) {
+                    resumeTopActivitiesLocked(targetStack, null, options);
+
+                    // Make sure to notify Keyguard as well if we are not running an app
+                    // transition later.
+                    if (!movedToFront) {
+                        notifyActivityDrawnForKeyguard();
+                    }
+                } else {
+                    ActivityOptions.abort(options);
+                }
+                updateUserStackLocked(r.userId, targetStack);
+                return ActivityManager.START_RETURN_INTENT_TO_CALLER;
+            }
+            if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
+                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
+                // The caller has requested to completely replace any
+                // existing task with its new activity.  Well that should
+                // not be too hard...
+                reuseTask = intentActivity.task;
+                reuseTask.performClearTaskLocked();
+                reuseTask.setIntent(r);
+            } else if ((launchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
+                    || launchSingleInstance || launchSingleTask) {
+                // In this situation we want to remove all activities
+                // from the task up to the one being started.  In most
+                // cases this means we are resetting the task to its
+                // initial state.
+                ActivityRecord top = intentActivity.task.performClearTaskLocked(r, launchFlags);
+                if (top != null) {
+                    if (top.frontOfTask) {
+                        // Activity aliases may mean we use different
+                        // intents for the top activity, so make sure
+                        // the task now has the identity of the new
+                        // intent.
+                        top.task.setIntent(r);
+                    }
+                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
+                    top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
+                } else {
+                    // A special case: we need to start the activity because it is not
+                    // currently running, and the caller has asked to clear the current
+                    // task to have this activity at the top.
+                    addingToTask = true;
+                    // Now pretend like this activity is being started by the top of its
+                    // task, so it is put in the right place.
+                    sourceRecord = intentActivity;
+                    TaskRecord task = sourceRecord.task;
+                    if (task != null && task.stack == null) {
+                        // Target stack got cleared when we all activities were removed
+                        // above. Go ahead and reset it.
+                        targetStack = computeStackFocus(
+                                sourceRecord, false /* newTask */, null /* bounds */);
+                        targetStack.addTask(task,
+                                !launchTaskBehind /* toTop */, "startActivityUnchecked");
+                    }
+
+                }
+            } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
+                // In this case the top activity on the task is the
+                // same as the one being launched, so we take that
+                // as a request to bring the task to the foreground.
+                // If the top activity in the task is the root
+                // activity, deliver this new intent to it if it
+                // desires.
+                if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || launchSingleTop)
+                        && intentActivity.realActivity.equals(r.realActivity)) {
+                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
+                            intentActivity.task);
+                    if (intentActivity.frontOfTask) {
+                        intentActivity.task.setIntent(r);
+                    }
+                    intentActivity.deliverNewIntentLocked(callingUid, r.intent,
+                            r.launchedFromPackage);
+                } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
+                    // In this case we are launching the root activity
+                    // of the task, but with a different intent.  We
+                    // should start a new instance on top.
+                    addingToTask = true;
+                    sourceRecord = intentActivity;
+                }
+            } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
+                // In this case an activity is being launched in to an
+                // existing task, without resetting that task.  This
+                // is typically the situation of launching an activity
+                // from a notification or shortcut.  We want to place
+                // the new activity on top of the current task.
+                addingToTask = true;
+                sourceRecord = intentActivity;
+            } else if (!intentActivity.task.rootWasReset) {
+                // In this case we are launching in to an existing task
+                // that has not yet been started from its front door.
+                // The current task has been brought to the front.
+                // Ideally, we'd probably like to place this new task
+                // at the bottom of its stack, but that's a little hard
+                // to do with the current organization of the code so
+                // for now we'll just drop it.
+                intentActivity.task.setIntent(r);
+            }
+            if (!addingToTask && reuseTask == null) {
+                // We didn't do anything...  but it was needed (a.k.a., client
+                // don't use that intent!)  And for paranoia, make
+                // sure we have correctly resumed the top activity.
+                if (doResume) {
+                    targetStack.resumeTopActivityLocked(null, options);
+                    if (!movedToFront) {
+                        // Make sure to notify Keyguard as well if we are not running an app
+                        // transition later.
+                        notifyActivityDrawnForKeyguard();
+                    }
+                } else {
+                    ActivityOptions.abort(options);
+                }
+                updateUserStackLocked(r.userId, targetStack);
+                return ActivityManager.START_TASK_TO_FRONT;
+            }
         }
 
         //String uri = r.intent.toURI();
@@ -2458,7 +2443,7 @@
 
         // Should this be considered a new task?
         if (r.resultTo == null && inTask == null && !addingToTask
-                && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+                && (launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
             newTask = true;
             targetStack = computeStackFocus(r, newTask, newBounds);
             if (doResume) {
@@ -2644,6 +2629,37 @@
         return ActivityManager.START_SUCCESS;
     }
 
+    /**
+     * Decide whether the new activity should be inserted into an existing task. Returns null if not
+     * or an ActivityRecord with the task into which the new activity should be added.
+     */
+    private ActivityRecord getReusableIntentActivity(ActivityRecord r, TaskRecord inTask, Intent intent,
+            boolean launchSingleInstance, boolean launchSingleTask, int launchFlags) {
+        // We may want to try to place the new activity in to an existing task.  We always
+        // do this if the target activity is singleTask or singleInstance; we will also do
+        // this if NEW_TASK has been requested, and there is not an additional qualifier telling
+        // us to still place it in a new task: multi task, always doc mode, or being asked to
+        // launch this as a new task behind the current one.
+        boolean putIntoExistingTask = ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
+                (launchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
+                || launchSingleInstance || launchSingleTask;
+        // If bring to front is requested, and no result is requested and we have not
+        // been given an explicit task to launch in to, and
+        // we can find a task that was started with this same
+        // component, then instead of launching bring that one to the front.
+        putIntoExistingTask &= inTask == null && r.resultTo == null;
+        ActivityRecord intentActivity = null;
+        if (putIntoExistingTask) {
+            // See if there is a task to bring to the front.  If this is
+            // a SINGLE_INSTANCE activity, there can be one and only one
+            // instance of it in the history, and it is always in its own
+            // unique task, so we do a special search.
+            intentActivity = launchSingleInstance ?
+                    findActivityLocked(intent, r.info) : findTaskLocked(r);
+        }
+        return intentActivity;
+    }
+
     final void doPendingActivityLaunchesLocked(boolean doResume) {
         while (!mPendingActivityLaunches.isEmpty()) {
             PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
@@ -3122,6 +3138,14 @@
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stackId);
         mWindowManager.deferSurfaceLayout();
         try {
+
+            if (bounds != null && mWindowManager.isFullscreenBounds(stackId, bounds)) {
+                // The bounds passed in corresponds to the fullscreen bounds which we normally
+                // represent with null. Go ahead and set it to null so that all tasks configuration
+                // can have the right fullscreen state.
+                bounds = null;
+            }
+
             ActivityRecord r = stack.topRunningActivityLocked();
 
             mTmpBounds.clear();
@@ -4702,8 +4726,8 @@
     }
 
     class ActivityContainer extends android.app.IActivityContainer.Stub {
-        final static int FORCE_NEW_TASK_FLAGS = Intent.FLAG_ACTIVITY_NEW_TASK |
-                Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION;
+        final static int FORCE_NEW_TASK_FLAGS = FLAG_ACTIVITY_NEW_TASK |
+                FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION;
         final int mStackId;
         IActivityContainerCallback mCallback = null;
         final ActivityStack mStack;
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index e15bca6..1908f72 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -49,23 +49,12 @@
     // If true, enables the use of the screen auto-brightness adjustment setting.
     private static final boolean USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT = true;
 
-    // The maximum range of gamma adjustment possible using the screen
-    // auto-brightness adjustment setting.
-    private static final float SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA = 3.0f;
-
-    // Period of time in which to consider light samples in milliseconds.
-    private static final int AMBIENT_LIGHT_HORIZON = 10000;
-
     // Hysteresis constraints for brightening or darkening.
     // The recent lux must have changed by at least this fraction relative to the
     // current ambient lux before a change will be considered.
     private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f;
     private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f;
 
-    // The intercept used for the weighting calculation. This is used in order to keep all possible
-    // weighting values positive.
-    private static final int WEIGHTING_INTERCEPT = AMBIENT_LIGHT_HORIZON;
-
     // How long the current sensor reading is assumed to be valid beyond the current time.
     // This provides a bit of prediction, as well as ensures that the weight for the last sample is
     // non-zero, which in turn ensures that the total weight is non-zero.
@@ -132,6 +121,13 @@
     // and only then decide whether to change brightness.
     private final boolean mResetAmbientLuxAfterWarmUpConfig;
 
+    // Period of time in which to consider light samples in milliseconds.
+    private final int mAmbientLightHorizon;
+
+    // The intercept used for the weighting calculation. This is used in order to keep all possible
+    // weighting values positive.
+    private final int mWeightingIntercept;
+
     // Amount of time to delay auto-brightness after screen on while waiting for
     // the light sensor to warm-up in milliseconds.
     // May be 0 if no warm-up is required.
@@ -179,6 +175,10 @@
     // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter)
     private float mScreenAutoBrightnessAdjustment = 0.0f;
 
+    // The maximum range of gamma adjustment possible using the screen
+    // auto-brightness adjustment setting.
+    private float mScreenAutoBrightnessAdjustmentMaxGamma;
+
     // The last screen auto-brightness gamma.  (For printing in dump() only.)
     private float mLastScreenAutoBrightnessGamma = 1.0f;
 
@@ -197,7 +197,8 @@
             SensorManager sensorManager, Spline autoBrightnessSpline, int lightSensorWarmUpTime,
             int brightnessMin, int brightnessMax, float dozeScaleFactor,
             int lightSensorRate, long brighteningLightDebounceConfig,
-            long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig) {
+            long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
+            int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma ) {
         mCallbacks = callbacks;
         mTwilight = LocalServices.getService(TwilightManager.class);
         mSensorManager = sensorManager;
@@ -210,9 +211,12 @@
         mBrighteningLightDebounceConfig = brighteningLightDebounceConfig;
         mDarkeningLightDebounceConfig = darkeningLightDebounceConfig;
         mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;
+        mAmbientLightHorizon = ambientLightHorizon;
+        mWeightingIntercept = ambientLightHorizon;
+        mScreenAutoBrightnessAdjustmentMaxGamma = autoBrightnessAdjustmentMaxGamma;
 
         mHandler = new AutomaticBrightnessHandler(looper);
-        mAmbientLightRingBuffer = new AmbientLightRingBuffer(mLightSensorRate);
+        mAmbientLightRingBuffer = new AmbientLightRingBuffer(mLightSensorRate, mAmbientLightHorizon);
 
         if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
             mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
@@ -266,6 +270,7 @@
         pw.println("  mLightSensorEnabled=" + mLightSensorEnabled);
         pw.println("  mLightSensorEnableTime=" + TimeUtils.formatUptime(mLightSensorEnableTime));
         pw.println("  mAmbientLux=" + mAmbientLux);
+        pw.println("  mAmbientLightHorizon=" + mAmbientLightHorizon);
         pw.println("  mBrighteningLuxThreshold=" + mBrighteningLuxThreshold);
         pw.println("  mDarkeningLuxThreshold=" + mDarkeningLuxThreshold);
         pw.println("  mLastObservedLux=" + mLastObservedLux);
@@ -274,6 +279,7 @@
         pw.println("  mAmbientLightRingBuffer=" + mAmbientLightRingBuffer);
         pw.println("  mScreenAutoBrightness=" + mScreenAutoBrightness);
         pw.println("  mScreenAutoBrightnessAdjustment=" + mScreenAutoBrightnessAdjustment);
+        pw.println("  mScreenAutoBrightnessAdjustmentMaxGamma=" + mScreenAutoBrightnessAdjustmentMaxGamma);
         pw.println("  mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
         pw.println("  mDozing=" + mDozing);
     }
@@ -309,7 +315,7 @@
 
     private void applyLightSensorMeasurement(long time, float lux) {
         mRecentLightSamples++;
-        mAmbientLightRingBuffer.prune(time - AMBIENT_LIGHT_HORIZON);
+        mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);
         mAmbientLightRingBuffer.push(time, lux);
 
         // Remember this sample value.
@@ -360,14 +366,14 @@
         return sum / totalWeight;
     }
 
-    private static float calculateWeight(long startDelta, long endDelta) {
+    private float calculateWeight(long startDelta, long endDelta) {
         return weightIntegral(endDelta) - weightIntegral(startDelta);
     }
 
-    // Evaluates the integral of y = x + WEIGHTING_INTERCEPT. This is always positive for the
+    // Evaluates the integral of y = x + mWeightingIntercept. This is always positive for the
     // horizon we're looking at and provides a non-linear weighting for light samples.
-    private static float weightIntegral(long x) {
-        return x * (x * 0.5f + WEIGHTING_INTERCEPT);
+    private float weightIntegral(long x) {
+        return x * (x * 0.5f + mWeightingIntercept);
     }
 
     private long nextAmbientLightBrighteningTransition(long time) {
@@ -396,7 +402,7 @@
 
     private void updateAmbientLux() {
         long time = SystemClock.uptimeMillis();
-        mAmbientLightRingBuffer.prune(time - AMBIENT_LIGHT_HORIZON);
+        mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);
         updateAmbientLux(time);
     }
 
@@ -470,7 +476,7 @@
 
         if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
                 && mScreenAutoBrightnessAdjustment != 0.0f) {
-            final float adjGamma = MathUtils.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA,
+            final float adjGamma = MathUtils.pow(mScreenAutoBrightnessAdjustmentMaxGamma,
                     Math.min(1.0f, Math.max(-1.0f, -mScreenAutoBrightnessAdjustment)));
             gamma *= adjGamma;
             if (DEBUG) {
@@ -653,8 +659,8 @@
         private int mEnd;
         private int mCount;
 
-        public AmbientLightRingBuffer(long lightSensorRate) {
-            mCapacity = (int) Math.ceil(AMBIENT_LIGHT_HORIZON * BUFFER_SLACK / lightSensorRate);
+        public AmbientLightRingBuffer(long lightSensorRate, int ambientLightHorizon) {
+            mCapacity = (int) Math.ceil(ambientLightHorizon * BUFFER_SLACK / lightSensorRate);
             mRingLux = new float[mCapacity];
             mRingTime = new long[mCapacity];
         }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 7b49530..433d887 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -311,6 +311,11 @@
                 com.android.internal.R.integer.config_autoBrightnessDarkeningLightDebounce);
         boolean autoBrightnessResetAmbientLuxAfterWarmUp = resources.getBoolean(
                 com.android.internal.R.bool.config_autoBrightnessResetAmbientLuxAfterWarmUp);
+        int ambientLightHorizon = resources.getInteger(
+                com.android.internal.R.integer.config_autoBrightnessAmbientLightHorizon);
+        float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
+                com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
+                1, 1);
 
         if (mUseSoftwareAutoBrightnessConfig) {
             int[] lux = resources.getIntArray(
@@ -348,7 +353,8 @@
                         lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
                         mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
                         brighteningLightDebounce, darkeningLightDebounce,
-                        autoBrightnessResetAmbientLuxAfterWarmUp);
+                        autoBrightnessResetAmbientLuxAfterWarmUp,
+                        ambientLightHorizon, autoBrightnessAdjustmentMaxGamma);
             }
         }
 
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index e0a9975..7ac3c4b 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -189,7 +189,7 @@
     protected void handleEnumerate(long deviceId, int[] fingerIds, int[] groupIds) {
         if (fingerIds.length != groupIds.length) {
             Slog.w(TAG, "fingerIds and groupIds differ in length: f[]="
-                    + fingerIds + ", g[]=" + groupIds);
+                    + Arrays.toString(fingerIds) + ", g[]=" + Arrays.toString(groupIds));
             return;
         }
         if (DEBUG) Slog.w(TAG, "Enumerate: f[]=" + fingerIds + ", g[]=" + groupIds);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index f2d0031..8b37383 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -213,6 +213,7 @@
     private static native void nativeMonitor(long ptr);
     private static native void nativeSetPointerIconShape(long ptr, int iconId);
     private static native void nativeReloadPointerIcons(long ptr);
+    private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
 
     // Input event injection constants defined in InputDispatcher.h.
     private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
@@ -1451,6 +1452,12 @@
         nativeSetPointerIconShape(mPtr, iconId);
     }
 
+    // Binder call
+    @Override
+    public void setCustomPointerIcon(PointerIcon icon) {
+        nativeSetCustomPointerIcon(mPtr, icon);
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index bc9f520..88ab2c6 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -88,6 +88,7 @@
 import java.io.StringReader;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.Map.Entry;
 import java.util.Properties;
@@ -1599,7 +1600,7 @@
         switch (status) {
             case GPS_REQUEST_AGPS_DATA_CONN:
                 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
-                Log.v(TAG, "Received SUPL IP addr[]: " + ipaddr);
+                Log.v(TAG, "Received SUPL IP addr[]: " + Arrays.toString(ipaddr));
                 InetAddress connectionIpAddress = null;
                 if (ipaddr != null) {
                     try {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3a8a988..e0f85c5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -436,12 +436,6 @@
     final String[] mSeparateProcesses;
     final boolean mIsUpgrade;
 
-    // This is where all application persistent data goes.
-    final File mAppDataDir;
-
-    // This is where all application persistent data goes for secondary users.
-    final File mUserAppDataDir;
-
     /** The location for ASEC container files on internal storage. */
     final String mAsecInternalPath;
 
@@ -953,7 +947,7 @@
 
     // Recordkeeping of restore-after-install operations that are currently in flight
     // between the Package Manager and the Backup Manager
-    class PostInstallData {
+    static class PostInstallData {
         public InstallArgs args;
         public PackageInstalledInfo res;
 
@@ -1070,7 +1064,7 @@
                         }
                         long timeInMillis;
                         try {
-                            timeInMillis = Long.parseLong(timeInMillisString.toString());
+                            timeInMillis = Long.parseLong(timeInMillisString);
                         } catch (NumberFormatException e) {
                             throw new IOException("Failed to parse " + timeInMillisString
                                                   + " as a long.", e);
@@ -1987,12 +1981,10 @@
             Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
 
             File dataDir = Environment.getDataDirectory();
-            mAppDataDir = new File(dataDir, "data");
             mAppInstallDir = new File(dataDir, "app");
             mAppLib32InstallDir = new File(dataDir, "app-lib");
             mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
             mAsecInternalPath = new File(dataDir, "app-asec").getPath();
-            mUserAppDataDir = new File(dataDir, "user");
             mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
 
             sUserManager = new UserManagerService(context, this, mPackages);
@@ -3368,14 +3360,6 @@
         }
     }
 
-    private void checkValidCaller(int uid, int userId) {
-        if (UserHandle.getUserId(uid) == userId || uid == Process.SYSTEM_UID || uid == 0)
-            return;
-
-        throw new SecurityException("Caller uid=" + uid
-                + " is not privileged to communicate with user=" + userId);
-    }
-
     @Override
     public int checkPermission(String permName, String pkgName, int userId) {
         if (!sUserManager.exists(userId)) {
@@ -4102,10 +4086,12 @@
         synchronized (mPackages) {
             if (mProtectedBroadcasts.contains(actionName)) {
                 return true;
-            } else if (actionName != null
-                    && actionName.startsWith("android.net.netmon.lingerExpired")) {
-                // TODO: remove this terrible hack
-                return true;
+            } else if (actionName != null) {
+                // TODO: remove these terrible hacks
+                if (actionName.startsWith("android.net.netmon.lingerExpired")
+                        || actionName.startsWith("com.android.server.sip.SipWakeupTimer")) {
+                    return true;
+                }
             }
         }
         return false;
@@ -10497,7 +10483,7 @@
             ArrayList<IntentFilter> result = new ArrayList<>();
             for (int n=0; n<count; n++) {
                 PackageParser.Activity activity = pkg.activities.get(n);
-                if (activity.intents != null || activity.intents.size() > 0) {
+                if (activity.intents != null && activity.intents.size() > 0) {
                     result.addAll(activity.intents);
                 }
             }
@@ -10916,7 +10902,7 @@
         }
     }
 
-    class MoveInfo {
+    static class MoveInfo {
         final int moveId;
         final String fromUuid;
         final String toUuid;
@@ -12222,7 +12208,7 @@
         }
     }
 
-    class PackageInstalledInfo {
+    static class PackageInstalledInfo {
         String name;
         int uid;
         // The set of users that originally had this package installed.
@@ -13163,10 +13149,6 @@
         }
     }
 
-    private static boolean isMultiArch(PackageSetting ps) {
-        return (ps.pkgFlags & ApplicationInfo.FLAG_MULTIARCH) != 0;
-    }
-
     private static boolean isMultiArch(ApplicationInfo info) {
         return (info.flags & ApplicationInfo.FLAG_MULTIARCH) != 0;
     }
@@ -13179,10 +13161,6 @@
         return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
     }
 
-    private static boolean isExternal(ApplicationInfo info) {
-        return (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
-    }
-
     private static boolean isEphemeral(PackageParser.Package pkg) {
         return pkg.applicationInfo.isEphemeralApp();
     }
@@ -13866,7 +13844,7 @@
         return ret;
     }
 
-    private final class ClearStorageConnection implements ServiceConnection {
+    private final static class ClearStorageConnection implements ServiceConnection {
         IMediaContainerService mContainerService;
 
         @Override
@@ -15116,7 +15094,9 @@
                 // First, verify that this is a valid class name.
                 PackageParser.Package pkg = pkgSetting.pkg;
                 if (pkg == null || !pkg.hasComponentClassName(className)) {
-                    if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
+                    if (pkg != null &&
+                            pkg.applicationInfo.targetSdkVersion >=
+                                    Build.VERSION_CODES.JELLY_BEAN) {
                         throw new IllegalArgumentException("Component class " + className
                                 + " does not exist in " + packageName);
                     } else {
@@ -17326,7 +17306,7 @@
         }
     }
 
-    private final class OnPermissionChangeListeners extends Handler {
+    private final static class OnPermissionChangeListeners extends Handler {
         private static final int MSG_ON_PERMISSIONS_CHANGED = 1;
 
         private final RemoteCallbackList<IOnPermissionsChangeListener> mPermissionListeners =
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b9a9d6e..dff6e3f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3056,13 +3056,22 @@
             hideRecentApps(true, false);
         }
 
-        // Handle keyboard language switching.
+        // Handle keyboard layout switching.
+        // TODO: Deprecate this behavior when we fully migrate to IME subtype-based layout rotation.
+        if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_SPACE
+                && ((metaState & KeyEvent.META_CTRL_MASK) != 0)) {
+            int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
+            mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
+            return -1;
+        }
+
+        // Handle input method switching.
         if (down && repeatCount == 0
                 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
                         || (keyCode == KeyEvent.KEYCODE_SPACE
-                                && (metaState & KeyEvent.META_CTRL_MASK) != 0))) {
-            int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
-            mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
+                                && (metaState & KeyEvent.META_META_MASK) != 0))) {
+            final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0;
+            mWindowManagerFuncs.switchInputMethod(forwardDirection);
             return -1;
         }
         if (mLanguageSwitchKeyPressed && !down
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 4b6db99..d888c56 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -53,7 +53,6 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.service.trust.TrustAgentService;
 import android.util.ArraySet;
@@ -681,7 +680,9 @@
         public boolean isDeviceSecure(int userId) throws RemoteException {
             userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
                     false /* allowAll */, true /* requireFull */, "isDeviceSecure", null);
-            userId = resolveProfileParent(userId);
+            if (!LockPatternUtils.isSeparateWorkChallengeEnabled()) {
+                userId = resolveProfileParent(userId);
+            }
 
             long token = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index fd5c704..b49641f 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -19,6 +19,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -122,21 +123,6 @@
     // True if the windows associated with this token should be cropped to their stack bounds.
     boolean mCropWindowsToStack;
 
-    // This application will have its window replaced due to relaunch. This allows window manager
-    // to differentiate between simple removal of a window and replacement. In the latter case it
-    // will preserve the old window until the new one is drawn.
-    boolean mWillReplaceWindow;
-    // If true, the replaced window was already requested to be removed.
-    boolean mReplacingRemoveRequested;
-    // Whether the replacement of the window should trigger app transition animation.
-    boolean mAnimateReplacingWindow;
-    // If not null, the window that will be used to replace the old one. This is being set when
-    // the window is added and unset when this window reports its first draw.
-    WindowState mReplacingWindow;
-    // Whether the new window has replaced the old one, so the old one can be removed without
-    // blinking.
-    boolean mHasReplacedWindow;
-
     AppWindowToken(WindowManagerService _service, IApplicationToken _token,
             boolean _voiceInteraction) {
         super(_service, _token.asBinder(),
@@ -392,6 +378,62 @@
         }
     }
 
+    void setReplacingWindows(boolean animate) {
+        if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken
+                + " with replacing windows.");
+
+        for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+            final WindowState w = allAppWindows.get(i);
+            w.setReplacing(animate);
+        }
+        if (animate) {
+            // Set-up dummy animation so we can start treating windows associated with this
+            // token like they are in transition before the new app window is ready for us to
+            // run the real transition animation.
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
+                    "setReplacingWindow() Setting dummy animation on: " + this);
+            mAppAnimator.setDummyAnimation();
+        }
+    }
+
+    void addWindow(WindowState w) {
+        for (int i = allAppWindows.size() - 1; i >= 0; i--) {
+            WindowState candidate = allAppWindows.get(i);
+            if (candidate.mWillReplaceWindow && candidate.mReplacingWindow == null &&
+                    candidate.getWindowTag().equals(w.getWindowTag().toString())) {
+                candidate.mReplacingWindow = w;
+            }
+        }
+        allAppWindows.add(w);
+    }
+
+    boolean waitingForReplacement() {
+        for (int i = allAppWindows.size() -1; i >= 0; i--) {
+            WindowState candidate = allAppWindows.get(i);
+            if (candidate.mWillReplaceWindow) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void clearTimedoutReplaceesLocked() {
+        for (int i = allAppWindows.size() - 1; i >= 0;
+             // removeWindowLocked at bottom of loop may remove multiple entries from
+             // allAppWindows if the window to be removed has child windows. It also may
+             // not remove any windows from allAppWindows at all if win is exiting and
+             // currently animating away. This ensures that winNdx is monotonically decreasing
+             // and never beyond allAppWindows bounds.
+             i = Math.min(i - 1, allAppWindows.size() - 1)) {
+            WindowState candidate = allAppWindows.get(i);
+            if (candidate.mWillReplaceWindow == false) {
+                continue;
+            }
+            candidate.mWillReplaceWindow = false;
+            service.removeWindowLocked(candidate);
+        }
+    }
+
     @Override
     void dump(PrintWriter pw, String prefix) {
         super.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 49d9efe..b961879 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -144,6 +144,14 @@
         return true;
     }
 
+    boolean isFullscreenBounds(Rect bounds) {
+        if (mDisplayContent == null || bounds == null) {
+            return true;
+        }
+        mDisplayContent.getLogicalDisplayRect(mTmpRect);
+        return mTmpRect.equals(bounds);
+    }
+
     private boolean setBounds(Rect bounds) {
         boolean oldFullscreen = mFullscreen;
         int rotation = Surface.ROTATION_0;
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 3db9ae0..2e424d0 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -506,7 +506,7 @@
                 inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
             }
 
-            replacing = replacing || (w.mAppToken != null && w.mAppToken.mWillReplaceWindow);
+            replacing = replacing || w.mWillReplaceWindow;
 
             // If the app is executing an animation because the keyguard is going away,
             // keep the wallpaper during the animation so it doesn't flicker out.
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index a6523a4..6a5183f 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -918,10 +918,6 @@
     }
 
     void requestRemovalOfReplacedWindows(WindowState win) {
-        final AppWindowToken token = win.mAppToken;
-        if (token != null && token.mWillReplaceWindow && token.mReplacingWindow == win) {
-            token.mHasReplacedWindow = true;
-        }
         mRemoveReplacedWindows = true;
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index a49bb31..845100d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -36,7 +36,7 @@
     static final boolean DEBUG_RESIZE = false;
     static final boolean DEBUG = false;
     static final boolean DEBUG_ADD_REMOVE = false;
-    static final boolean DEBUG_FOCUS = false;
+    static final boolean DEBUG_FOCUS = true;
     static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
     static final boolean DEBUG_ANIM = false;
     static final boolean DEBUG_KEYGUARD = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 816cab7..456c416 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -186,6 +186,7 @@
 import android.view.WindowManagerPolicy;
 import android.view.WindowManagerPolicy.PointerEventListener;
 import android.view.animation.Animation;
+import android.view.inputmethod.InputMethodManagerInternal;
 import android.widget.Toast;
 
 import com.android.internal.R;
@@ -268,6 +269,9 @@
     /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
     static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
 
+    /** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */
+    static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000;
+
     /** Amount of time to allow a last ANR message to exist before freeing the memory. */
     static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours
     /**
@@ -458,7 +462,6 @@
     EmulatorDisplayOverlay mEmulatorDisplayOverlay;
 
     final float[] mTmpFloats = new float[9];
-    final Rect mTmpContentRect = new Rect();
 
     boolean mDisplayReady;
     boolean mSafeMode;
@@ -1350,10 +1353,7 @@
         final AppWindowToken appToken = win.mAppToken;
         if (appToken != null) {
             if (addToToken) {
-                appToken.allAppWindows.add(win);
-            }
-            if (appToken.mWillReplaceWindow) {
-                appToken.mReplacingWindow = win;
+                appToken.addWindow(win);
             }
         }
     }
@@ -2088,14 +2088,15 @@
     }
 
     private void prepareWindowReplacementTransition(AppWindowToken atoken) {
-        if (atoken == null || !atoken.mWillReplaceWindow || !atoken.mAnimateReplacingWindow) {
+        if (atoken == null) {
             return;
         }
         atoken.allDrawn = false;
         WindowState replacedWindow = null;
         for (int i = atoken.windows.size() - 1; i >= 0 && replacedWindow == null; i--) {
             WindowState candidate = atoken.windows.get(i);
-            if (candidate.mExiting) {
+            if (candidate.mExiting && candidate.mWillReplaceWindow
+                    && candidate.mAnimateReplacingWindow) {
                 replacedWindow = candidate;
             }
         }
@@ -2195,7 +2196,7 @@
                 + " app-animation="
                 + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
                 + " mWillReplaceWindow="
-                + (win.mAppToken != null ? win.mAppToken.mWillReplaceWindow : false)
+                + win.mWillReplaceWindow
                 + " inPendingTransaction="
                 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
                 + " mDisplayFrozen=" + mDisplayFrozen);
@@ -2207,13 +2208,13 @@
         // animation wouldn't be seen.
         if (win.mHasSurface && okToDisplay()) {
             final AppWindowToken appToken = win.mAppToken;
-            if (appToken != null && appToken.mWillReplaceWindow) {
+            if (win.mWillReplaceWindow) {
                 // This window is going to be replaced. We need to keep it around until the new one
                 // gets added, then we will get rid of this one.
                 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Preserving " + win + " until the new one is "
                         + "added");
                 win.mExiting = true;
-                appToken.mReplacingRemoveRequested = true;
+                win.mReplacingRemoveRequested = true;
                 Binder.restoreCallingIdentity(origId);
                 return;
             }
@@ -4052,7 +4053,7 @@
         // transition animation
         // * or this is an opening app and windows are being replaced.
         if (wtoken.hidden == visible || (wtoken.hidden && wtoken.mIsExiting) ||
-                (visible && wtoken.mWillReplaceWindow)) {
+                (visible && wtoken.waitingForReplacement())) {
             boolean changed = false;
             if (DEBUG_APP_TRANSITIONS) Slog.v(
                 TAG_WM, "Changing app " + wtoken + " hidden=" + wtoken.hidden
@@ -4829,6 +4830,17 @@
         }
     }
 
+    /** Returns true if the input bounds corresponds to the fullscreen bounds the stack is on. */
+    public boolean isFullscreenBounds(int stackId, Rect bounds) {
+        synchronized (mWindowMap) {
+            final TaskStack stack = mStackIdToStack.get(stackId);
+            if (stack == null || bounds == null) {
+                return true;
+            }
+            return stack.isFullscreenBounds(bounds);
+        }
+    }
+
     /**
      * Re-sizes a stack and its containing tasks.
      * @param stackId Id of stack to resize.
@@ -5297,6 +5309,16 @@
 
     // Called by window manager policy.  Not exposed externally.
     @Override
+    public void switchInputMethod(boolean forwardDirection) {
+        final InputMethodManagerInternal inputMethodManagerInternal =
+                LocalServices.getService(InputMethodManagerInternal.class);
+        if (inputMethodManagerInternal != null) {
+            inputMethodManagerInternal.switchInputMethod(forwardDirection);
+        }
+    }
+
+    // Called by window manager policy.  Not exposed externally.
+    @Override
     public void shutdown(boolean confirm) {
         ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
     }
@@ -7493,6 +7515,8 @@
         public static final int TWO_FINGER_SCROLL_START = 45;
         public static final int SHOW_NON_RESIZEABLE_DOCK_TOAST = 46;
 
+        public static final int WINDOW_REPLACEMENT_TIMEOUT = 47;
+
         /**
          * Used to denote that an integer field in a message will not be used.
          */
@@ -8075,6 +8099,13 @@
                     toast.show();
                 }
                 break;
+                case WINDOW_REPLACEMENT_TIMEOUT: {
+                    final AppWindowToken token = (AppWindowToken) msg.obj;
+                    synchronized (mWindowMap) {
+                        token.clearTimedoutReplaceesLocked();
+                    }
+                }
+                break;
             }
             if (DEBUG_WINDOW_TRACE) {
                 Slog.v(TAG_WM, "handleMessage: exit");
@@ -8597,7 +8628,7 @@
                 final int numTokens = tokens.size();
                 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
                     final AppWindowToken wtoken = tokens.get(tokenNdx);
-                    if (wtoken.mIsExiting && !wtoken.mWillReplaceWindow) {
+                    if (wtoken.mIsExiting && !wtoken.waitingForReplacement()) {
                         continue;
                     }
                     i = reAddAppWindowsLocked(displayContent, i, wtoken);
@@ -8706,8 +8737,8 @@
     private void forceHigherLayerIfNeeded(WindowState w, WindowStateAnimator winAnimator,
             AppWindowToken wtoken) {
         boolean force = false;
-        if (wtoken.mWillReplaceWindow && wtoken.mReplacingWindow != w
-                && wtoken.mAnimateReplacingWindow) {
+
+        if (w.mWillReplaceWindow) {
             // We know that we will be animating a relaunching window in the near future,
             // which will receive a z-order increase. We want the replaced window to
             // immediately receive the same treatment, e.g. to be above the dock divider.
@@ -10223,26 +10254,20 @@
      * @param token Application token for which the activity will be relaunched.
      */
     public void setReplacingWindow(IBinder token, boolean animate) {
+        AppWindowToken appWindowToken = null;
         synchronized (mWindowMap) {
-            AppWindowToken appWindowToken = findAppWindowToken(token);
+            appWindowToken = findAppWindowToken(token);
             if (appWindowToken == null || !appWindowToken.isVisible()) {
                 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token " + token);
                 return;
             }
-            if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + appWindowToken
-                    + " as replacing window.");
-            appWindowToken.mWillReplaceWindow = true;
-            appWindowToken.mHasReplacedWindow = false;
-            appWindowToken.mAnimateReplacingWindow = animate;
+            appWindowToken.setReplacingWindows(animate);
+        }
 
-            if (animate) {
-                // Set-up dummy animation so we can start treating windows associated with this
-                // token like they are in transition before the new app window is ready for us to
-                // run the real transition animation.
-                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
-                        "setReplacingWindow() Setting dummy animation on: " + appWindowToken);
-                appWindowToken.mAppAnimator.setDummyAnimation();
-            }
+        if (appWindowToken != null) {
+            mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
+            mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_REPLACEMENT_TIMEOUT, appWindowToken),
+                    WINDOW_REPLACEMENT_TIMEOUT_DURATION);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5a589e3..e4a6806 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -75,6 +75,7 @@
 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -403,6 +404,18 @@
     // used to start an entering animation earlier.
     public boolean mSurfaceSaved = false;
 
+    // This window will be replaced due to relaunch. This allows window manager
+    // to differentiate between simple removal of a window and replacement. In the latter case it
+    // will preserve the old window until the new one is drawn.
+    boolean mWillReplaceWindow = false;
+    // If true, the replaced window was already requested to be removed.
+    boolean mReplacingRemoveRequested = false;
+    // Whether the replacement of the window should trigger app transition animation.
+    boolean mAnimateReplacingWindow = false;
+    // If not null, the window that will be used to replace the old one. This is being set when
+    // the window is added and unset when this window reports its first draw.
+    WindowState mReplacingWindow = null;
+
     /**
      * Wake lock for drawing.
      * Even though it's slightly more expensive to do so, we will use a separate wake lock
@@ -580,8 +593,7 @@
     @Override
     public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf,
             Rect osf) {
-        if (mAppToken != null && mAppToken.mWillReplaceWindow
-                && (mExiting || !mAppToken.mReplacingRemoveRequested)) {
+        if (mWillReplaceWindow && (mExiting || !mReplacingRemoveRequested)) {
             // This window is being replaced and either already got information that it's being
             // removed or we are still waiting for some information. Because of this we don't
             // want to apply any more changes to it, so it remains in this state until new window
@@ -1343,17 +1355,17 @@
     }
 
     void maybeRemoveReplacedWindow() {
-        AppWindowToken token = mAppToken;
-        if (token != null && token.mWillReplaceWindow && token.mReplacingWindow == this
-                && token.mHasReplacedWindow) {
-            if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replacing window: " + this);
-            token.mWillReplaceWindow = false;
-            token.mAnimateReplacingWindow = false;
-            token.mReplacingRemoveRequested = false;
-            token.mReplacingWindow = null;
-            token.mHasReplacedWindow = false;
-            for (int i = token.allAppWindows.size() - 1; i >= 0; i--) {
-                final WindowState win = token.allAppWindows.get(i);
+        if (mAppToken == null) {
+            return;
+        }
+        for (int i = mAppToken.allAppWindows.size() - 1; i >= 0; i--) {
+            final WindowState win = mAppToken.allAppWindows.get(i);
+            if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + win);
+            if (win.mWillReplaceWindow && win.mReplacingWindow == this) {
+                win.mWillReplaceWindow = false;
+                win.mAnimateReplacingWindow = false;
+                win.mReplacingRemoveRequested = false;
+                win.mReplacingWindow = null;
                 if (win.mExiting) {
                     mService.removeWindowInnerLocked(win);
                 }
@@ -2161,7 +2173,7 @@
             + " " + getWindowTag();
     }
 
-    private CharSequence getWindowTag() {
+    CharSequence getWindowTag() {
         CharSequence tag = mAttrs.getTitle();
         if (tag == null || tag.length() <= 0) {
             tag = mAttrs.packageName;
@@ -2259,4 +2271,12 @@
     boolean isChildWindow() {
         return mAttachedWindow != null;
     }
+
+    void setReplacing(boolean animate) {
+        if ((mAttrs.privateFlags & PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH) == 0) {
+            mWillReplaceWindow = true;
+            mReplacingWindow = null;
+            mAnimateReplacingWindow = animate;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index cd82a5f..d4001cd 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1192,7 +1192,7 @@
         // different stack. If we suddenly crop it to the new stack bounds, it might get cut off.
         // We don't want it to happen, so we let it ignore the stack bounds until it gets removed.
         // The window that will replace it will abide them.
-        if (isAnimating() && (appToken.mWillReplaceWindow || w.inDockedWorkspace()
+        if (isAnimating() && (w.mWillReplaceWindow || w.inDockedWorkspace()
                 || w.inFreeformWorkspace())) {
             return;
         }
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index bd2912d..9675d2f 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -131,13 +131,9 @@
     }
 
     void destroyInTransaction() {
-        if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
-            RuntimeException e = null;
-            if (!HIDE_STACK_CRAWLS) {
-                e = new RuntimeException();
-                e.fillInStackTrace();
-            }
-        }
+        //        if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+        Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(3));
+        //        }
         try {
             mSurfaceControl.destroy();
             mSurfaceShown = false;
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 50bdf25..160c97f 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -96,6 +96,7 @@
     private long mUserActivityTimeout = -1;
     private boolean mUpdateRotation = false;
     private final Rect mTmpStartRect = new Rect();
+    private final Rect mTmpContentRect = new Rect();
 
     // Set to true when the display contains content to show the user.
     // When false, the display manager may choose to mirror or blank the display.
@@ -862,8 +863,8 @@
             mService.mScreenRect.set(0, 0, dw, dh);
         }
 
-        mService.mPolicy.getContentRectLw(mService.mTmpContentRect);
-        displayContent.resize(mService.mTmpContentRect);
+        mService.mPolicy.getContentRectLw(mTmpContentRect);
+        displayContent.resize(mTmpContentRect);
 
         int seq = mService.mLayoutSeq+1;
         if (seq < 0) seq = 0;
@@ -1192,7 +1193,7 @@
                     // if app window is removed, or window relayout to invisible. We don't want to
                     // clear it out for windows that get replaced, because the animation depends on
                     // the flag to remove the replaced window.
-                    if (win.mAppToken == null || !win.mAppToken.mWillReplaceWindow) {
+                    if (!win.mWillReplaceWindow) {
                         win.mExiting = false;
                     }
                     if (win.mWinAnimator.mAnimLayer > layer) {
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 9c9a5da..4c8474a 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -206,6 +206,7 @@
     void reloadCalibration();
     void setPointerIconShape(int32_t iconId);
     void reloadPointerIcons();
+    void setCustomPointerIcon(const SpriteIcon& icon);
 
     /* --- InputReaderPolicyInterface implementation --- */
 
@@ -248,6 +249,7 @@
     virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources,
             std::map<int32_t, PointerAnimation>* outAnimationResources);
     virtual int32_t getDefaultPointerIconId();
+    virtual int32_t getCustomPointerIconId();
 
 private:
     sp<InputManager> mInputManager;
@@ -790,6 +792,14 @@
     }
 }
 
+void NativeInputManager::setCustomPointerIcon(const SpriteIcon& icon) {
+    AutoMutex _l(mLock);
+    sp<PointerController> controller = mLocked.pointerController.promote();
+    if (controller != NULL) {
+        controller->setCustomPointerIcon(icon);
+    }
+}
+
 TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
         JNIEnv *env, jfloatArray matrixArr) {
     ScopedFloatArrayRO matrix(env, matrixArr);
@@ -1090,6 +1100,10 @@
     return POINTER_ICON_STYLE_ARROW;
 }
 
+int32_t NativeInputManager::getCustomPointerIconId() {
+    return POINTER_ICON_STYLE_CUSTOM;
+}
+
 // ----------------------------------------------------------------------------
 
 static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
@@ -1437,6 +1451,20 @@
     im->reloadPointerIcons();
 }
 
+static void nativeSetCustomPointerIcon(JNIEnv* env, jclass /* clazz */,
+                                       jlong ptr, jobject iconObj) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    PointerIcon pointerIcon;
+    android_view_PointerIcon_getLoadedIcon(env, iconObj, &pointerIcon);
+
+    SpriteIcon spriteIcon;
+    pointerIcon.bitmap.copyTo(&spriteIcon.bitmap, kN32_SkColorType);
+    spriteIcon.hotSpotX = pointerIcon.hotSpotX;
+    spriteIcon.hotSpotY = pointerIcon.hotSpotY;
+    im->setCustomPointerIcon(spriteIcon);
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gInputManagerMethods[] = {
@@ -1499,6 +1527,8 @@
             (void*) nativeSetPointerIconShape },
     { "nativeReloadPointerIcons", "(J)V",
             (void*) nativeReloadPointerIcons },
+    { "nativeSetCustomPointerIcon", "(JLandroid/view/PointerIcon;)V",
+            (void*) nativeSetCustomPointerIcon },
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
index 998bb68..35e3ef4 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
@@ -22,6 +22,7 @@
 import android.util.ArraySet;
 import android.util.Pair;
 import java.io.IOException;
+import java.net.InetAddress;
 import java.net.Socket;
 import java.net.URL;
 import java.security.KeyStore;
@@ -34,6 +35,7 @@
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLSocket;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
 
@@ -103,6 +105,15 @@
         TestUtils.assertConnectionFails(context, "developer.android.com", 443);
         TestUtils.assertUrlConnectionFails(context, "google.com", 443);
         TestUtils.assertUrlConnectionSucceeds(context, "android.com", 443);
+        // Check that sockets created without the hostname fail with per-domain configs
+        SSLSocket socket = (SSLSocket) context.getSocketFactory()
+                .createSocket(InetAddress.getByName("android.com"), 443);
+        try {
+        socket.startHandshake();
+        socket.getInputStream();
+        fail();
+        } catch (IOException expected) {
+        }
     }
 
     public void testBasicPinning() throws Exception {
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
index 0ddfa77..a0b5a6e 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
@@ -296,7 +296,7 @@
         sbuf.append("serviceType:").append(mServiceType);
         sbuf.append(" status:").append(Status.toString(mStatus));
         sbuf.append(" srcAddr:").append(mDevice.deviceAddress);
-        sbuf.append(" data:").append(mData);
+        sbuf.append(" data:").append(Arrays.toString(mData));
         return sbuf.toString();
     }