Merge "Expose TelephonyManager#{set,get}DataEnabled."
diff --git a/api/current.txt b/api/current.txt
index b9cc43d..3914021 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1357,6 +1357,7 @@
     field public static final int toYDelta = 16843209; // 0x10101c9
     field public static final int toYScale = 16843205; // 0x10101c5
     field public static final int toolbarStyle = 16843946; // 0x10104aa
+    field public static final int tooltip = 16844084; // 0x1010534
     field public static final int top = 16843182; // 0x10101ae
     field public static final int topBright = 16842955; // 0x10100cb
     field public static final int topDark = 16842951; // 0x10100c7
@@ -19914,6 +19915,7 @@
     field public static final int SCO_AUDIO_STATE_CONNECTING = 2; // 0x2
     field public static final int SCO_AUDIO_STATE_DISCONNECTED = 0; // 0x0
     field public static final int SCO_AUDIO_STATE_ERROR = -1; // 0xffffffff
+    field public static final int STREAM_ACCESSIBILITY = 10; // 0xa
     field public static final int STREAM_ALARM = 4; // 0x4
     field public static final int STREAM_DTMF = 8; // 0x8
     field public static final int STREAM_MUSIC = 3; // 0x3
@@ -37684,6 +37686,7 @@
     field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
     field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
+    field public static final java.lang.String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
     field public static final int APPTYPE_CSIM = 4; // 0x4
     field public static final int APPTYPE_ISIM = 5; // 0x5
     field public static final int APPTYPE_RUIM = 3; // 0x3
@@ -37703,11 +37706,15 @@
     field public static final int DATA_CONNECTING = 1; // 0x1
     field public static final int DATA_DISCONNECTED = 0; // 0x0
     field public static final int DATA_SUSPENDED = 3; // 0x3
+    field public static final java.lang.String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT";
     field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
+    field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
+    field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
     field public static final java.lang.String EXTRA_STATE = "state";
     field public static final java.lang.String EXTRA_STATE_IDLE;
     field public static final java.lang.String EXTRA_STATE_OFFHOOK;
     field public static final java.lang.String EXTRA_STATE_RINGING;
+    field public static final java.lang.String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER";
     field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
     field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
     field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
@@ -42829,6 +42836,7 @@
     method public java.lang.Object getTag(int);
     method public int getTextAlignment();
     method public int getTextDirection();
+    method public final java.lang.CharSequence getTooltip();
     method public final int getTop();
     method protected float getTopFadingEdgeStrength();
     method protected int getTopPaddingOffset();
@@ -43117,6 +43125,7 @@
     method public void setTag(int, java.lang.Object);
     method public void setTextAlignment(int);
     method public void setTextDirection(int);
+    method public final void setTooltip(java.lang.CharSequence);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
     method public final void setTransitionName(java.lang.String);
@@ -59089,8 +59098,8 @@
     method public static void rotate(java.util.List<?>, int);
     method public static void shuffle(java.util.List<?>);
     method public static void shuffle(java.util.List<?>, java.util.Random);
-    method public static <E> java.util.Set<E> singleton(E);
-    method public static <E> java.util.List<E> singletonList(E);
+    method public static <T> java.util.Set<T> singleton(T);
+    method public static <T> java.util.List<T> singletonList(T);
     method public static <K, V> java.util.Map<K, V> singletonMap(K, V);
     method public static <T extends java.lang.Comparable<? super T>> void sort(java.util.List<T>);
     method public static <T> void sort(java.util.List<T>, java.util.Comparator<? super T>);
diff --git a/api/system-current.txt b/api/system-current.txt
index bfa590c..bcf4897 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1468,6 +1468,7 @@
     field public static final int toYDelta = 16843209; // 0x10101c9
     field public static final int toYScale = 16843205; // 0x10101c5
     field public static final int toolbarStyle = 16843946; // 0x10104aa
+    field public static final int tooltip = 16844084; // 0x1010534
     field public static final int top = 16843182; // 0x10101ae
     field public static final int topBright = 16842955; // 0x10100cb
     field public static final int topDark = 16842951; // 0x10100c7
@@ -21476,6 +21477,7 @@
     field public static final int SCO_AUDIO_STATE_CONNECTING = 2; // 0x2
     field public static final int SCO_AUDIO_STATE_DISCONNECTED = 0; // 0x0
     field public static final int SCO_AUDIO_STATE_ERROR = -1; // 0xffffffff
+    field public static final int STREAM_ACCESSIBILITY = 10; // 0xa
     field public static final int STREAM_ALARM = 4; // 0x4
     field public static final int STREAM_DTMF = 8; // 0x8
     field public static final int STREAM_MUSIC = 3; // 0x3
@@ -35380,6 +35382,7 @@
     field public static final java.lang.String ACTION_VR_LISTENER_SETTINGS = "android.settings.VR_LISTENER_SETTINGS";
     field public static final java.lang.String ACTION_WEBVIEW_SETTINGS = "android.settings.WEBVIEW_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_IP_SETTINGS = "android.settings.WIFI_IP_SETTINGS";
+    field public static final java.lang.String ACTION_WIFI_SAVED_NETWORK_SETTINGS = "android.settings.WIFI_SAVED_NETWORK_SETTINGS";
     field public static final java.lang.String ACTION_WIFI_SETTINGS = "android.settings.WIFI_SETTINGS";
     field public static final java.lang.String ACTION_WIRELESS_SETTINGS = "android.settings.WIRELESS_SETTINGS";
     field public static final java.lang.String AUTHORITY = "settings";
@@ -45995,6 +45998,7 @@
     method public java.lang.Object getTag(int);
     method public int getTextAlignment();
     method public int getTextDirection();
+    method public final java.lang.CharSequence getTooltip();
     method public final int getTop();
     method protected float getTopFadingEdgeStrength();
     method protected int getTopPaddingOffset();
@@ -46283,6 +46287,7 @@
     method public void setTag(int, java.lang.Object);
     method public void setTextAlignment(int);
     method public void setTextDirection(int);
+    method public final void setTooltip(java.lang.CharSequence);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
     method public final void setTransitionName(java.lang.String);
@@ -62614,8 +62619,8 @@
     method public static void rotate(java.util.List<?>, int);
     method public static void shuffle(java.util.List<?>);
     method public static void shuffle(java.util.List<?>, java.util.Random);
-    method public static <E> java.util.Set<E> singleton(E);
-    method public static <E> java.util.List<E> singletonList(E);
+    method public static <T> java.util.Set<T> singleton(T);
+    method public static <T> java.util.List<T> singletonList(T);
     method public static <K, V> java.util.Map<K, V> singletonMap(K, V);
     method public static <T extends java.lang.Comparable<? super T>> void sort(java.util.List<T>);
     method public static <T> void sort(java.util.List<T>, java.util.Comparator<? super T>);
diff --git a/api/test-current.txt b/api/test-current.txt
index 02372eb..2dcb743 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1357,6 +1357,7 @@
     field public static final int toYDelta = 16843209; // 0x10101c9
     field public static final int toYScale = 16843205; // 0x10101c5
     field public static final int toolbarStyle = 16843946; // 0x10104aa
+    field public static final int tooltip = 16844084; // 0x1010534
     field public static final int top = 16843182; // 0x10101ae
     field public static final int topBright = 16842955; // 0x10100cb
     field public static final int topDark = 16842951; // 0x10100c7
@@ -19995,6 +19996,7 @@
     field public static final int SCO_AUDIO_STATE_CONNECTING = 2; // 0x2
     field public static final int SCO_AUDIO_STATE_DISCONNECTED = 0; // 0x0
     field public static final int SCO_AUDIO_STATE_ERROR = -1; // 0xffffffff
+    field public static final int STREAM_ACCESSIBILITY = 10; // 0xa
     field public static final int STREAM_ALARM = 4; // 0x4
     field public static final int STREAM_DTMF = 8; // 0x8
     field public static final int STREAM_MUSIC = 3; // 0x3
@@ -37774,6 +37776,7 @@
     field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
     field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
+    field public static final java.lang.String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
     field public static final int APPTYPE_CSIM = 4; // 0x4
     field public static final int APPTYPE_ISIM = 5; // 0x5
     field public static final int APPTYPE_RUIM = 3; // 0x3
@@ -37793,11 +37796,15 @@
     field public static final int DATA_CONNECTING = 1; // 0x1
     field public static final int DATA_DISCONNECTED = 0; // 0x0
     field public static final int DATA_SUSPENDED = 3; // 0x3
+    field public static final java.lang.String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT";
     field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
+    field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
+    field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
     field public static final java.lang.String EXTRA_STATE = "state";
     field public static final java.lang.String EXTRA_STATE_IDLE;
     field public static final java.lang.String EXTRA_STATE_OFFHOOK;
     field public static final java.lang.String EXTRA_STATE_RINGING;
+    field public static final java.lang.String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER";
     field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
     field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
     field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
@@ -43074,6 +43081,8 @@
     method public java.lang.Object getTag(int);
     method public int getTextAlignment();
     method public int getTextDirection();
+    method public final java.lang.CharSequence getTooltip();
+    method public android.view.View getTooltipView();
     method public final int getTop();
     method protected float getTopFadingEdgeStrength();
     method protected int getTopPaddingOffset();
@@ -43362,6 +43371,7 @@
     method public void setTag(int, java.lang.Object);
     method public void setTextAlignment(int);
     method public void setTextDirection(int);
+    method public final void setTooltip(java.lang.CharSequence);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
     method public final void setTransitionName(java.lang.String);
@@ -43644,10 +43654,14 @@
     method public static deprecated int getEdgeSlop();
     method public static deprecated int getFadingEdgeLength();
     method public static deprecated long getGlobalActionKeyTimeout();
+    method public static int getHoverTooltipHideShortTimeout();
+    method public static int getHoverTooltipHideTimeout();
+    method public static int getHoverTooltipShowTimeout();
     method public static int getJumpTapTimeout();
     method public static int getKeyRepeatDelay();
     method public static int getKeyRepeatTimeout();
     method public static int getLongPressTimeout();
+    method public static int getLongPressTooltipHideTimeout();
     method public static deprecated int getMaximumDrawingCacheSize();
     method public static deprecated int getMaximumFlingVelocity();
     method public static deprecated int getMinimumFlingVelocity();
@@ -59350,8 +59364,8 @@
     method public static void rotate(java.util.List<?>, int);
     method public static void shuffle(java.util.List<?>);
     method public static void shuffle(java.util.List<?>, java.util.Random);
-    method public static <E> java.util.Set<E> singleton(E);
-    method public static <E> java.util.List<E> singletonList(E);
+    method public static <T> java.util.Set<T> singleton(T);
+    method public static <T> java.util.List<T> singletonList(T);
     method public static <K, V> java.util.Map<K, V> singletonMap(K, V);
     method public static <T extends java.lang.Comparable<? super T>> void sort(java.util.List<T>);
     method public static <T> void sort(java.util.List<T>, java.util.Comparator<? super T>);
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 38e3572..bfa6d34 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -61,6 +61,11 @@
      */
     public static final int APP_TRANSITION_TIMEOUT = 3;
 
+    /**
+     * Verify that calling app has access to the given provider.
+     */
+    public abstract String checkContentProviderAccess(String authority, int userId);
+
     // Called by the power manager.
     public abstract void onWakefulnessChanged(int wakefulness);
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1aa13a9..f052bf7 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1309,8 +1309,19 @@
         }
 
         @Override
-        public final void updateTimePrefs(boolean is24Hour) {
-            DateFormat.set24HourTimePref(is24Hour);
+        public final void updateTimePrefs(int timeFormatPreference) {
+            final Boolean timeFormatPreferenceBool;
+            // For convenience we are using the Intent extra values.
+            if (timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_12_HOUR) {
+                timeFormatPreferenceBool = Boolean.FALSE;
+            } else if (timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_24_HOUR) {
+                timeFormatPreferenceBool = Boolean.TRUE;
+            } else {
+                // timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_LOCALE_DEFAULT
+                // (or unknown).
+                timeFormatPreferenceBool = null;
+            }
+            DateFormat.set24HourTimePref(timeFormatPreferenceBool);
         }
 
         @Override
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 191cc49..ba6bc15 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -240,7 +240,9 @@
     /** @hide Control whether an application is allowed to run in the background. */
     public static final int OP_RUN_IN_BACKGROUND = 63;
     /** @hide */
-    public static final int _NUM_OP = 64;
+    public static final int OP_AUDIO_ACCESSIBILITY_VOLUME = 64;
+    /** @hide */
+    public static final int _NUM_OP = 65;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -452,6 +454,7 @@
             OP_TURN_SCREEN_ON,
             OP_GET_ACCOUNTS,
             OP_RUN_IN_BACKGROUND,
+            OP_AUDIO_ACCESSIBILITY_VOLUME,
     };
 
     /**
@@ -523,6 +526,7 @@
             null,
             OPSTR_GET_ACCOUNTS,
             null,
+            null, // OP_AUDIO_ACCESSIBILITY_VOLUME
     };
 
     /**
@@ -594,6 +598,7 @@
             "TURN_ON_SCREEN",
             "GET_ACCOUNTS",
             "RUN_IN_BACKGROUND",
+            "AUDIO_ACCESSIBILITY_VOLUME",
     };
 
     /**
@@ -665,6 +670,7 @@
             null, // no permission for turning the screen on
             Manifest.permission.GET_ACCOUNTS,
             null, // no permission for running in background
+            null, // no permission for changing accessibility volume
     };
 
     /**
@@ -737,6 +743,7 @@
             null, // TURN_ON_SCREEN
             null, // GET_ACCOUNTS
             null, // RUN_IN_BACKGROUND
+            UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_ACCESSIBILITY_VOLUME
     };
 
     /**
@@ -808,6 +815,7 @@
             false, // TURN_ON_SCREEN
             false, // GET_ACCOUNTS
             false, // RUN_IN_BACKGROUND
+            false, // AUDIO_ACCESSIBILITY_VOLUME
     };
 
     /**
@@ -878,6 +886,7 @@
             AppOpsManager.MODE_ALLOWED,  // OP_TURN_ON_SCREEN
             AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED,  // OP_RUN_IN_BACKGROUND
+            AppOpsManager.MODE_ALLOWED,  // OP_AUDIO_ACCESSIBILITY_VOLUME
     };
 
     /**
@@ -952,6 +961,7 @@
             false,
             false,
             false,
+            false, // OP_AUDIO_ACCESSIBILITY_VOLUME
     };
 
     /**
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 6a73829..ef2db4a 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -16,17 +16,19 @@
 
 package android.app;
 
+import android.os.Build;
 import android.os.Trace;
 import android.util.ArrayMap;
 import com.android.internal.os.PathClassLoaderFactory;
 import dalvik.system.PathClassLoader;
 
-class ApplicationLoaders {
+/** @hide */
+public class ApplicationLoaders {
     public static ApplicationLoaders getDefault() {
         return gApplicationLoaders;
     }
 
-    public ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
+    ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled,
                                       String librarySearchPath, String libraryPermittedPath,
                                       ClassLoader parent) {
         /*
@@ -80,6 +82,19 @@
         }
     }
 
+    /**
+     * Creates a classloader for the WebView APK and places it in the cache of loaders maintained
+     * by this class. This is used in the WebView zygote, where its presence in the cache speeds up
+     * startup and enables memory sharing.
+     */
+    public ClassLoader createAndCacheWebViewClassLoader(String packagePath, String libsPath) {
+      // The correct paths are calculated by WebViewZygote in the system server and passed to
+      // us here. We hardcode the other parameters: WebView always targets the current SDK,
+      // does not need to use non-public system libraries, and uses the base classloader as its
+      // parent to permit usage of the cache.
+      return getClassLoader(packagePath, Build.VERSION.SDK_INT, false, libsPath, null, null);
+    }
+
     private static native void setupVulkanLayerPath(ClassLoader classLoader, String librarySearchPath);
 
     /**
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 8c9837b..6b962b9 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -138,7 +138,7 @@
     void scheduleTranslucentConversionComplete(IBinder token, boolean timeout);
     void setProcessState(int state);
     void scheduleInstallProvider(in ProviderInfo provider);
-    void updateTimePrefs(boolean is24Hour);
+    void updateTimePrefs(int timeFormatPreference);
     void scheduleCancelVisibleBehind(IBinder token);
     void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean enabled);
     void scheduleEnterAnimationComplete(IBinder token);
@@ -152,4 +152,4 @@
             IVoiceInteractor voiceInteractor);
     void handleTrustStorageUpdate();
     void attachAgent(String path);
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index da99e80..725cc29 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -21,6 +21,7 @@
 import android.app.trust.ITrustManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.os.Binder;
 import android.os.RemoteException;
@@ -45,6 +46,7 @@
     private IWindowManager mWM;
     private ITrustManager mTrustManager;
     private IUserManager mUserManager;
+    private Context mContext;
 
     /**
      * Intent used to prompt user for device credentials.
@@ -87,8 +89,12 @@
         Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL);
         intent.putExtra(EXTRA_TITLE, title);
         intent.putExtra(EXTRA_DESCRIPTION, description);
-        // For security reasons, only allow this to come from system settings.
-        intent.setPackage("com.android.settings");
+        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            intent.setPackage("com.google.android.apps.wearable.settings");
+        } else {
+            // For security reasons, only allow this to come from system settings.
+            intent.setPackage("com.android.settings");
+        }
         return intent;
     }
 
@@ -109,8 +115,12 @@
         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");
+        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            intent.setPackage("com.google.android.apps.wearable.settings");
+        } else {
+            // For security reasons, only allow this to come from system settings.
+            intent.setPackage("com.android.settings");
+        }
         return intent;
     }
 
@@ -193,7 +203,8 @@
     }
 
 
-    KeyguardManager() throws ServiceNotFoundException {
+    KeyguardManager(Context context) throws ServiceNotFoundException {
+        mContext = context;
         mWM = WindowManagerGlobal.getWindowManagerService();
         mTrustManager = ITrustManager.Stub.asInterface(
                 ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE));
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index a38377e..94d24e4 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -339,39 +339,43 @@
          * concatenation of both apps' shared library lists.
          */
 
-        String instrumentationPackageName = activityThread.mInstrumentationPackageName;
-        String instrumentationAppDir = activityThread.mInstrumentationAppDir;
-        String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
-        String instrumentationLibDir = activityThread.mInstrumentationLibDir;
-
-        String instrumentedAppDir = activityThread.mInstrumentedAppDir;
-        String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
-        String instrumentedLibDir = activityThread.mInstrumentedLibDir;
         String[] instrumentationLibs = null;
+        // activityThread will be null when called from the WebView zygote; just assume
+        // no instrumentation applies in this case.
+        if (activityThread != null) {
+            String instrumentationPackageName = activityThread.mInstrumentationPackageName;
+            String instrumentationAppDir = activityThread.mInstrumentationAppDir;
+            String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
+            String instrumentationLibDir = activityThread.mInstrumentationLibDir;
 
-        if (appDir.equals(instrumentationAppDir)
-                || appDir.equals(instrumentedAppDir)) {
-            outZipPaths.clear();
-            outZipPaths.add(instrumentationAppDir);
-            if (instrumentationSplitAppDirs != null) {
-                Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
-            }
-            if (!instrumentationAppDir.equals(instrumentedAppDir)) {
-                outZipPaths.add(instrumentedAppDir);
-                if (instrumentedSplitAppDirs != null) {
-                    Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
+            String instrumentedAppDir = activityThread.mInstrumentedAppDir;
+            String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
+            String instrumentedLibDir = activityThread.mInstrumentedLibDir;
+
+            if (appDir.equals(instrumentationAppDir)
+                    || appDir.equals(instrumentedAppDir)) {
+                outZipPaths.clear();
+                outZipPaths.add(instrumentationAppDir);
+                if (instrumentationSplitAppDirs != null) {
+                    Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
                 }
-            }
-
-            if (outLibPaths != null) {
-                outLibPaths.add(instrumentationLibDir);
-                if (!instrumentationLibDir.equals(instrumentedLibDir)) {
-                    outLibPaths.add(instrumentedLibDir);
+                if (!instrumentationAppDir.equals(instrumentedAppDir)) {
+                    outZipPaths.add(instrumentedAppDir);
+                    if (instrumentedSplitAppDirs != null) {
+                        Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
+                    }
                 }
-            }
 
-            if (!instrumentedAppDir.equals(instrumentationAppDir)) {
-                instrumentationLibs = getLibrariesFor(instrumentationPackageName);
+                if (outLibPaths != null) {
+                    outLibPaths.add(instrumentationLibDir);
+                    if (!instrumentationLibDir.equals(instrumentedLibDir)) {
+                        outLibPaths.add(instrumentedLibDir);
+                    }
+                }
+
+                if (!instrumentedAppDir.equals(instrumentationAppDir)) {
+                    instrumentationLibs = getLibrariesFor(instrumentationPackageName);
+                }
             }
         }
 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index f38c0d8..3ecc309 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -322,10 +322,10 @@
             }});
 
         registerService(Context.KEYGUARD_SERVICE, KeyguardManager.class,
-                new StaticServiceFetcher<KeyguardManager>() {
+                new CachedServiceFetcher<KeyguardManager>() {
             @Override
-            public KeyguardManager createService() throws ServiceNotFoundException {
-                return new KeyguardManager();
+            public KeyguardManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+                return new KeyguardManager(ctx);
             }});
 
         registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c87de9a..50589fe 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4186,13 +4186,21 @@
             = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
 
     /**
-     * Optional boolean extra for {@link #ACTION_TIME_CHANGED} that indicates the
-     * user has set their time format preferences to the 24 hour format.
+     * Optional int extra for {@link #ACTION_TIME_CHANGED} that indicates the
+     * user has set their time format preference. See {@link #EXTRA_TIME_PREF_VALUE_USE_12_HOUR},
+     * {@link #EXTRA_TIME_PREF_VALUE_USE_24_HOUR} and
+     * {@link #EXTRA_TIME_PREF_VALUE_USE_LOCALE_DEFAULT}. The value must not be negative.
      *
      * @hide for internal use only.
      */
     public static final String EXTRA_TIME_PREF_24_HOUR_FORMAT =
             "android.intent.extra.TIME_PREF_24_HOUR_FORMAT";
+    /** @hide */
+    public static final int EXTRA_TIME_PREF_VALUE_USE_12_HOUR = 0;
+    /** @hide */
+    public static final int EXTRA_TIME_PREF_VALUE_USE_24_HOUR = 1;
+    /** @hide */
+    public static final int EXTRA_TIME_PREF_VALUE_USE_LOCALE_DEFAULT = 2;
 
     /** {@hide} */
     public static final String EXTRA_REASON = "android.intent.extra.REASON";
diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java
index 29ea5a0..945858e6 100644
--- a/core/java/android/content/pm/ParceledListSlice.java
+++ b/core/java/android/content/pm/ParceledListSlice.java
@@ -17,15 +17,12 @@
 package android.content.pm;
 
 import android.os.Binder;
-import android.os.Build;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.util.Log;
 
-import dalvik.system.VMRuntime;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -130,11 +127,7 @@
     }
 
     public List<T> getList() {
-        if (VMRuntime.getRuntime().getTargetSdkVersion() > Build.VERSION_CODES.N_MR1) {
-            return Collections.unmodifiableList(mList);
-        } else {
-            return mList;
-        }
+        return mList;
     }
 
     @Override
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 1ac9fca..e7436be 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -108,6 +108,26 @@
      */
     public static final int TAG_SYSTEM_RESTORE = 0xFFFFFF04;
 
+    /** @hide */
+    public static final int TAG_SYSTEM_DHCP = 0xFFFFFF05;
+    /** @hide */
+    public static final int TAG_SYSTEM_NTP = 0xFFFFFF06;
+    /** @hide */
+    public static final int TAG_SYSTEM_PROBE = 0xFFFFFF07;
+    /** @hide */
+    public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFF08;
+    /** @hide */
+    public static final int TAG_SYSTEM_GPS = 0xFFFFFF09;
+    /** @hide */
+    public static final int TAG_SYSTEM_PAC = 0xFFFFFF0A;
+
+    /**
+     * Sockets that are strictly local on device; never hits network.
+     *
+     * @hide
+     */
+    public static final int TAG_SYSTEM_LOCAL = 0xFFFFFFAA;
+
     private static INetworkStatsService sStatsService;
 
     private synchronized static INetworkStatsService getStatsService() {
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index d31036c..6a751e8 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -77,6 +77,7 @@
     private static native boolean native_get_boolean(String key, boolean def);
     private static native void native_set(String key, String def);
     private static native void native_add_change_callback();
+    private static native void native_report_sysprop_change();
 
     /**
      * Get the value for the given key.
@@ -195,4 +196,11 @@
             }
         }
     }
+
+    /*
+     * Notifies listeners that a system property has changed
+     */
+    public static void reportSyspropChanged() {
+        native_report_sysprop_change();
+    }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index afbc09b..0946906 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -369,6 +369,22 @@
             "android.settings.WIFI_IP_SETTINGS";
 
     /**
+     * Activity Action: Show settings to allow configuration of Wi-Fi saved networks.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_WIFI_SAVED_NETWORK_SETTINGS =
+            "android.settings.WIFI_SAVED_NETWORK_SETTINGS";
+
+    /**
      * Activity Action: Show settings to allow configuration of Bluetooth.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
index 3734831..5f27e34 100644
--- a/core/java/android/service/autofill/AutoFillService.java
+++ b/core/java/android/service/autofill/AutoFillService.java
@@ -114,6 +114,11 @@
 
     private HandlerCaller mHandlerCaller;
 
+    /**
+     * {@inheritDoc}
+     *
+     * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}.
+     */
     @Override
     public void onCreate() {
         super.onCreate();
diff --git a/core/java/android/service/autofill/IAutoFillCallback.aidl b/core/java/android/service/autofill/IAutoFillCallback.aidl
index db8ef96..d6d4f39 100644
--- a/core/java/android/service/autofill/IAutoFillCallback.aidl
+++ b/core/java/android/service/autofill/IAutoFillCallback.aidl
@@ -21,7 +21,7 @@
 /**
  * @hide
  */
-interface IAutoFillCallback {
+oneway interface IAutoFillCallback {
     void autofill(in List values);
     void showError(String message);
 }
diff --git a/core/java/android/service/autofill/IAutoFillManagerService.aidl b/core/java/android/service/autofill/IAutoFillManagerService.aidl
index cab073f..76a2561 100644
--- a/core/java/android/service/autofill/IAutoFillManagerService.aidl
+++ b/core/java/android/service/autofill/IAutoFillManagerService.aidl
@@ -23,7 +23,7 @@
  *
  * {@hide}
  */
-interface IAutoFillManagerService {
+oneway interface IAutoFillManagerService {
 
     /**
      * Request auto-fill on the top activity of a given user.
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index e3e911c..bb122e5 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -25,7 +25,7 @@
  * @hide
  */
 interface IAutoFillService {
-    void onConnected();
-    void onDisconnected();
+    oneway void onConnected();
+    oneway void onDisconnected();
     IResultReceiver getAssistReceiver();
 }
diff --git a/core/java/android/util/BootTimingsTraceLog.java b/core/java/android/util/BootTimingsTraceLog.java
new file mode 100644
index 0000000..2e4319c
--- /dev/null
+++ b/core/java/android/util/BootTimingsTraceLog.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.util;
+
+import android.os.Build;
+import android.os.SystemClock;
+import android.os.Trace;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+/**
+ * Helper class for reporting boot timing metrics.
+ * @hide
+ */
+public class BootTimingsTraceLog {
+    // Debug boot time for every step if it's non-user build.
+    private static final boolean DEBUG_BOOT_TIME = !"user".equals(Build.TYPE);
+    private final Deque<Pair<String, Long>> mStartTimes
+            = DEBUG_BOOT_TIME ? new ArrayDeque<>() : null;
+    private final String mTag;
+    private long mTraceTag;
+
+    public BootTimingsTraceLog(String tag, long traceTag) {
+        mTag = tag;
+        mTraceTag = traceTag;
+    }
+
+    public void traceBegin(String name) {
+        Trace.traceBegin(mTraceTag, name);
+        if (DEBUG_BOOT_TIME) {
+            mStartTimes.push(Pair.create(name, SystemClock.elapsedRealtime()));
+        }
+    }
+
+    public void traceEnd() {
+        Trace.traceEnd(mTraceTag);
+        if (!DEBUG_BOOT_TIME) {
+            return;
+        }
+        if (mStartTimes.peek() == null) {
+            Slog.w(mTag, "traceEnd called more times than traceBegin");
+            return;
+        }
+        Pair<String, Long> event = mStartTimes.pop();
+        // Log the duration so it can be parsed by external tools for performance reporting
+        Slog.d(mTag, event.first + " took to complete: "
+                + (SystemClock.elapsedRealtime() - event.second) + "ms");
+    }
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 02a8521..84d7548 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -37,6 +37,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.TestApi;
 import android.annotation.UiThread;
 import android.content.ClipData;
 import android.content.Context;
@@ -111,6 +112,7 @@
 
 import com.android.internal.R;
 import com.android.internal.util.Predicate;
+import com.android.internal.view.TooltipPopup;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.widget.ScrollBarUtils;
 
@@ -1196,6 +1198,12 @@
 
     private static Paint sDebugPaint;
 
+    /**
+     * <p>Indicates this view can display a tooltip on hover or long press.</p>
+     * {@hide}
+     */
+    static final int TOOLTIP = 0x40000000;
+
     /** @hide */
     @IntDef(flag = true,
             value = {
@@ -3619,6 +3627,39 @@
 
     ListenerInfo mListenerInfo;
 
+    private static class TooltipInfo {
+        /**
+         * Text to be displayed in a tooltip popup.
+         */
+        @Nullable
+        CharSequence mTooltip;
+
+        /**
+         * View-relative position of the tooltip anchor point.
+         */
+        int mAnchorX;
+        int mAnchorY;
+
+        /**
+         * The tooltip popup.
+         */
+        @Nullable
+        TooltipPopup mTooltipPopup;
+
+        /**
+         * Set to true if the tooltip was shown as a result of a long click.
+         */
+        boolean mTooltipFromLongClick;
+
+        /**
+         * Keep these Runnables so that they can be used to reschedule.
+         */
+        Runnable mShowTooltipRunnable;
+        Runnable mHideTooltipRunnable;
+    }
+
+    TooltipInfo mTooltipInfo;
+
     // Temporary values used to hold (x,y) coordinates when delegating from the
     // two-arg performLongClick() method to the legacy no-arg version.
     private float mLongClickX = Float.NaN;
@@ -4576,6 +4617,9 @@
                     }
                     break;
 
+                case R.styleable.View_tooltip:
+                    setTooltip(a.getText(attr));
+                    break;
             }
         }
 
@@ -5712,6 +5756,11 @@
             final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
             handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
         }
+        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
+            if (!handled) {
+                handled = showLongClickTooltip((int) x, (int) y);
+            }
+        }
         if (handled) {
             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
         }
@@ -10603,17 +10652,21 @@
                 return true;
             }
 
-            // Long clickable items don't necessarily have to be clickable.
-            if (((mViewFlags & CLICKABLE) == CLICKABLE
-                    || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
-                    && (event.getRepeatCount() == 0)) {
-                // For the purposes of menu anchoring and drawable hotspots,
-                // key events are considered to be at the center of the view.
-                final float x = getWidth() / 2f;
-                final float y = getHeight() / 2f;
-                setPressed(true, x, y);
-                checkForLongClick(0, x, y);
-                return true;
+            if (event.getRepeatCount() == 0) {
+                // Long clickable items don't necessarily have to be clickable.
+                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
+                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
+                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
+                    // For the purposes of menu anchoring and drawable hotspots,
+                    // key events are considered to be at the center of the view.
+                    final float x = getWidth() / 2f;
+                    final float y = getHeight() / 2f;
+                    if (clickable) {
+                        setPressed(true, x, y);
+                    }
+                    checkForLongClick(0, x, y);
+                    return true;
+                }
             }
         }
 
@@ -11160,15 +11213,17 @@
         final int viewFlags = mViewFlags;
         final int action = event.getAction();
 
+        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
+                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
+                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
+
         if ((viewFlags & ENABLED_MASK) == DISABLED) {
             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
                 setPressed(false);
             }
             // A disabled view that is clickable still consumes the touch
             // events, it just doesn't respond to them.
-            return (((viewFlags & CLICKABLE) == CLICKABLE
-                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
-                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
+            return clickable;
         }
         if (mTouchDelegate != null) {
             if (mTouchDelegate.onTouchEvent(event)) {
@@ -11176,11 +11231,20 @@
             }
         }
 
-        if (((viewFlags & CLICKABLE) == CLICKABLE ||
-                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
-                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
+        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
             switch (action) {
                 case MotionEvent.ACTION_UP:
+                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
+                        handleTooltipUp();
+                    }
+                    if (!clickable) {
+                        removeTapCallback();
+                        removeLongPressCallback();
+                        mInContextButtonPress = false;
+                        mHasPerformedLongPress = false;
+                        mIgnoreNextUpEvent = false;
+                        break;
+                    }
                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
                         // take focus if we don't have it already and we should in
@@ -11196,7 +11260,7 @@
                             // state now (before scheduling the click) to ensure
                             // the user sees it.
                             setPressed(true, x, y);
-                       }
+                        }
 
                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
                             // This is a tap, so remove the longpress check
@@ -11236,6 +11300,11 @@
                 case MotionEvent.ACTION_DOWN:
                     mHasPerformedLongPress = false;
 
+                    if (!clickable) {
+                        checkForLongClick(0, x, y);
+                        break;
+                    }
+
                     if (performButtonActionOnTouchDown(event)) {
                         break;
                     }
@@ -11261,7 +11330,9 @@
                     break;
 
                 case MotionEvent.ACTION_CANCEL:
-                    setPressed(false);
+                    if (clickable) {
+                        setPressed(false);
+                    }
                     removeTapCallback();
                     removeLongPressCallback();
                     mInContextButtonPress = false;
@@ -11270,16 +11341,17 @@
                     break;
 
                 case MotionEvent.ACTION_MOVE:
-                    drawableHotspotChanged(x, y);
+                    if (clickable) {
+                        drawableHotspotChanged(x, y);
+                    }
 
                     // Be lenient about moving outside of buttons
                     if (!pointInView(x, y, mTouchSlop)) {
                         // Outside button
+                        // Remove any future long press/tap checks
                         removeTapCallback();
+                        removeLongPressCallback();
                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
-                            // Remove any future long press/tap checks
-                            removeLongPressCallback();
-
                             setPressed(false);
                         }
                     }
@@ -11311,7 +11383,7 @@
      */
     private void removeLongPressCallback() {
         if (mPendingCheckForLongPress != null) {
-          removeCallbacks(mPendingCheckForLongPress);
+            removeCallbacks(mPendingCheckForLongPress);
         }
     }
 
@@ -15379,6 +15451,10 @@
 
         cleanupDraw();
         mCurrentAnimation = null;
+
+        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
+            hideTooltip();
+        }
     }
 
     private void cleanupDraw() {
@@ -21031,7 +21107,7 @@
     }
 
     private void checkForLongClick(int delayOffset, float x, float y) {
-        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
+        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
             mHasPerformedLongPress = false;
 
             if (mPendingCheckForLongPress == null) {
@@ -21039,6 +21115,7 @@
             }
             mPendingCheckForLongPress.setAnchor(x, y);
             mPendingCheckForLongPress.rememberWindowAttachCount();
+            mPendingCheckForLongPress.rememberPressedState();
             postDelayed(mPendingCheckForLongPress,
                     ViewConfiguration.getLongPressTimeout() - delayOffset);
         }
@@ -22439,10 +22516,11 @@
         private int mOriginalWindowAttachCount;
         private float mX;
         private float mY;
+        private boolean mOriginalPressedState;
 
         @Override
         public void run() {
-            if (isPressed() && (mParent != null)
+            if ((mOriginalPressedState == isPressed()) && (mParent != null)
                     && mOriginalWindowAttachCount == mWindowAttachCount) {
                 if (performLongClick(mX, mY)) {
                     mHasPerformedLongPress = true;
@@ -22458,6 +22536,10 @@
         public void rememberWindowAttachCount() {
             mOriginalWindowAttachCount = mWindowAttachCount;
         }
+
+        public void rememberPressedState() {
+            mOriginalPressedState = isPressed();
+        }
     }
 
     private final class CheckForTap implements Runnable {
@@ -23246,6 +23328,12 @@
          */
         public Surface mDragSurface;
 
+
+        /**
+         * The view that currently has a tooltip displayed.
+         */
+        View mTooltipHost;
+
         /**
          * Creates a new set of attachment information with the specified
          * events handler and thread.
@@ -23982,4 +24070,167 @@
         return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
                 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
     }
+
+    /**
+     * Sets the tooltip text which will be displayed in a small popup next to the view.
+     * <p>
+     * The tooltip will be displayed:
+     * <li>On long click, unless is not handled otherwise (by OnLongClickListener or a context
+     * menu). </li>
+     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
+     *
+     * @param tooltip the tooltip text, or null if no tooltip is required
+     */
+    public final void setTooltip(@Nullable CharSequence tooltip) {
+        if (TextUtils.isEmpty(tooltip)) {
+            setFlags(0, TOOLTIP);
+            hideTooltip();
+            mTooltipInfo = null;
+        } else {
+            setFlags(TOOLTIP, TOOLTIP);
+            if (mTooltipInfo == null) {
+                mTooltipInfo = new TooltipInfo();
+                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
+                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
+            }
+            mTooltipInfo.mTooltip = tooltip;
+            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
+                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltip);
+            }
+        }
+    }
+
+    /**
+     * Returns the view's tooltip text.
+     *
+     * @return the tooltip text
+     */
+    @Nullable
+    public final CharSequence getTooltip() {
+        return mTooltipInfo != null ? mTooltipInfo.mTooltip : null;
+    }
+
+    private boolean showTooltip(int x, int y, boolean fromLongClick) {
+        if (mAttachInfo == null) {
+            return false;
+        }
+        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
+            return false;
+        }
+        final CharSequence tooltipText = getTooltip();
+        if (TextUtils.isEmpty(tooltipText)) {
+            return false;
+        }
+        hideTooltip();
+        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
+        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
+        mTooltipInfo.mTooltipPopup.show(this, x, y, tooltipText);
+        mAttachInfo.mTooltipHost = this;
+        return true;
+    }
+
+    void hideTooltip() {
+        if (mTooltipInfo == null) {
+            return;
+        }
+        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
+        if (mTooltipInfo.mTooltipPopup == null) {
+            return;
+        }
+        mTooltipInfo.mTooltipPopup.hide();
+        mTooltipInfo.mTooltipPopup = null;
+        mTooltipInfo.mTooltipFromLongClick = false;
+        if (mAttachInfo != null) {
+            mAttachInfo.mTooltipHost = null;
+        }
+    }
+
+    private boolean showLongClickTooltip(int x, int y) {
+        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
+        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
+        return showTooltip(x, y, true);
+    }
+
+    private void showHoverTooltip() {
+        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
+    }
+
+    boolean dispatchTooltipHoverEvent(MotionEvent event) {
+        if (mTooltipInfo == null) {
+            return false;
+        }
+        switch(event.getAction()) {
+            case MotionEvent.ACTION_HOVER_MOVE:
+                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
+                    break;
+                }
+                if (!mTooltipInfo.mTooltipFromLongClick) {
+                    if (mTooltipInfo.mTooltipPopup == null) {
+                        // Schedule showing the tooltip after a timeout.
+                        mTooltipInfo.mAnchorX = (int) event.getX();
+                        mTooltipInfo.mAnchorY = (int) event.getY();
+                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
+                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
+                                ViewConfiguration.getHoverTooltipShowTimeout());
+                    }
+
+                    // Hide hover-triggered tooltip after a period of inactivity.
+                    // Match the timeout used by NativeInputManager to hide the mouse pointer
+                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
+                    final int timeout;
+                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
+                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
+                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
+                    } else {
+                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
+                    }
+                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
+                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
+                }
+                return true;
+
+            case MotionEvent.ACTION_HOVER_EXIT:
+                if (!mTooltipInfo.mTooltipFromLongClick) {
+                    hideTooltip();
+                }
+                break;
+        }
+        return false;
+    }
+
+    void handleTooltipKey(KeyEvent event) {
+        switch (event.getAction()) {
+            case KeyEvent.ACTION_DOWN:
+                if (event.getRepeatCount() == 0) {
+                    hideTooltip();
+                }
+                break;
+
+            case KeyEvent.ACTION_UP:
+                handleTooltipUp();
+                break;
+        }
+    }
+
+    private void handleTooltipUp() {
+        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
+            return;
+        }
+        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
+        postDelayed(mTooltipInfo.mHideTooltipRunnable,
+                ViewConfiguration.getLongPressTooltipHideTimeout());
+    }
+
+    /**
+     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
+     * is not showing.
+     * @hide
+     */
+    @TestApi
+    public View getTooltipView() {
+        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
+            return null;
+        }
+        return mTooltipInfo.mTooltipPopup.getContentView();
+    }
 }
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 33b488f..6d2f850 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.TestApi;
 import android.app.AppGlobals;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -230,6 +231,29 @@
     private static final long ACTION_MODE_HIDE_DURATION_DEFAULT = 2000;
 
     /**
+     * Defines the duration in milliseconds before an end of a long press causes a tooltip to be
+     * hidden.
+     */
+    private static final int LONG_PRESS_TOOLTIP_HIDE_TIMEOUT = 1500;
+
+    /**
+     * Defines the duration in milliseconds before a hover event causes a tooltip to be shown.
+     */
+    private static final int HOVER_TOOLTIP_SHOW_TIMEOUT = 500;
+
+    /**
+     * Defines the duration in milliseconds before mouse inactivity causes a tooltip to be hidden.
+     * (default variant to be used when {@link View#SYSTEM_UI_FLAG_LOW_PROFILE} is not set).
+     */
+    private static final int HOVER_TOOLTIP_HIDE_TIMEOUT = 15000;
+
+    /**
+     * Defines the duration in milliseconds before mouse inactivity causes a tooltip to be hidden
+     * (short version to be used when {@link View#SYSTEM_UI_FLAG_LOW_PROFILE} is set).
+     */
+    private static final int HOVER_TOOLTIP_HIDE_SHORT_TIMEOUT = 3000;
+
+    /**
      * Configuration values for overriding {@link #hasPermanentMenuKey()} behavior.
      * These constants must match the definition in res/values/config.xml.
      */
@@ -800,4 +824,43 @@
     public boolean isFadingMarqueeEnabled() {
         return mFadingMarqueeEnabled;
     }
+
+    /**
+     * @return the duration in milliseconds before an end of a long press causes a tooltip to be
+     * hidden
+     * @hide
+     */
+    @TestApi
+    public static int getLongPressTooltipHideTimeout() {
+        return LONG_PRESS_TOOLTIP_HIDE_TIMEOUT;
+    }
+
+    /**
+     * @return the duration in milliseconds before a hover event causes a tooltip to be shown
+     * @hide
+     */
+    @TestApi
+    public static int getHoverTooltipShowTimeout() {
+        return HOVER_TOOLTIP_SHOW_TIMEOUT;
+    }
+
+    /**
+     * @return the duration in milliseconds before mouse inactivity causes a tooltip to be hidden
+     * (default variant to be used when {@link View#SYSTEM_UI_FLAG_LOW_PROFILE} is not set).
+     * @hide
+     */
+    @TestApi
+    public static int getHoverTooltipHideTimeout() {
+        return HOVER_TOOLTIP_HIDE_TIMEOUT;
+    }
+
+    /**
+     * @return the duration in milliseconds before mouse inactivity causes a tooltip to be hidden
+     * (shorter variant to be used when {@link View#SYSTEM_UI_FLAG_LOW_PROFILE} is set).
+     * @hide
+     */
+    @TestApi
+    public static int getHoverTooltipHideShortTimeout() {
+        return HOVER_TOOLTIP_HIDE_SHORT_TIMEOUT;
+    }
 }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index e39cb96..c0191ce 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -199,6 +199,13 @@
     // It might not have actually handled the hover event.
     private boolean mHoveredSelf;
 
+    // The child capable of showing a tooltip and currently under the pointer.
+    private View mTooltipHoverTarget;
+
+    // True if the view group is capable of showing a tooltip and the pointer is directly
+    // over the view group but not one of its child views.
+    private boolean mTooltipHoveredSelf;
+
     /**
      * Internal flags.
      *
@@ -1970,6 +1977,104 @@
         }
     }
 
+    @Override
+    boolean dispatchTooltipHoverEvent(MotionEvent event) {
+        final int action = event.getAction();
+        switch (action) {
+            case MotionEvent.ACTION_HOVER_ENTER:
+                break;
+
+            case MotionEvent.ACTION_HOVER_MOVE:
+                View newTarget = null;
+
+                // Check what the child under the pointer says about the tooltip.
+                final int childrenCount = mChildrenCount;
+                if (childrenCount != 0) {
+                    final float x = event.getX();
+                    final float y = event.getY();
+
+                    final ArrayList<View> preorderedList = buildOrderedChildList();
+                    final boolean customOrder = preorderedList == null
+                            && isChildrenDrawingOrderEnabled();
+                    final View[] children = mChildren;
+                    for (int i = childrenCount - 1; i >= 0; i--) {
+                        final int childIndex =
+                                getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
+                        final View child =
+                                getAndVerifyPreorderedView(preorderedList, children, childIndex);
+                        final PointF point = getLocalPoint();
+                        if (isTransformedTouchPointInView(x, y, child, point)) {
+                            if (dispatchTooltipHoverEvent(event, child)) {
+                                newTarget = child;
+                            }
+                            break;
+                        }
+                    }
+                    if (preorderedList != null) preorderedList.clear();
+                }
+
+                if (mTooltipHoverTarget != newTarget) {
+                    if (mTooltipHoverTarget != null) {
+                        event.setAction(MotionEvent.ACTION_HOVER_EXIT);
+                        mTooltipHoverTarget.dispatchTooltipHoverEvent(event);
+                        event.setAction(action);
+                    }
+                    mTooltipHoverTarget = newTarget;
+                }
+
+                if (mTooltipHoverTarget != null) {
+                    if (mTooltipHoveredSelf) {
+                        mTooltipHoveredSelf = false;
+                        event.setAction(MotionEvent.ACTION_HOVER_EXIT);
+                        super.dispatchTooltipHoverEvent(event);
+                        event.setAction(action);
+                    }
+                    return true;
+                }
+
+                mTooltipHoveredSelf = super.dispatchTooltipHoverEvent(event);
+                return mTooltipHoveredSelf;
+
+            case MotionEvent.ACTION_HOVER_EXIT:
+                if (mTooltipHoverTarget != null) {
+                    mTooltipHoverTarget.dispatchTooltipHoverEvent(event);
+                    mTooltipHoverTarget = null;
+                } else if (mTooltipHoveredSelf) {
+                    super.dispatchTooltipHoverEvent(event);
+                    mTooltipHoveredSelf = false;
+                }
+                break;
+        }
+        return false;
+    }
+
+    private boolean dispatchTooltipHoverEvent(MotionEvent event, View child) {
+        final boolean result;
+        if (!child.hasIdentityMatrix()) {
+            MotionEvent transformedEvent = getTransformedMotionEvent(event, child);
+            result = child.dispatchTooltipHoverEvent(transformedEvent);
+            transformedEvent.recycle();
+        } else {
+            final float offsetX = mScrollX - child.mLeft;
+            final float offsetY = mScrollY - child.mTop;
+            event.offsetLocation(offsetX, offsetY);
+            result = child.dispatchTooltipHoverEvent(event);
+            event.offsetLocation(-offsetX, -offsetY);
+        }
+        return result;
+    }
+
+    private void exitTooltipHoverTargets() {
+        if (mTooltipHoveredSelf || mTooltipHoverTarget != null) {
+            final long now = SystemClock.uptimeMillis();
+            MotionEvent event = MotionEvent.obtain(now, now,
+                    MotionEvent.ACTION_HOVER_EXIT, 0.0f, 0.0f, 0);
+            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+            dispatchTooltipHoverEvent(event);
+            event.recycle();
+        }
+    }
+
     /** @hide */
     @Override
     protected boolean hasHoveredChild() {
@@ -3186,6 +3291,7 @@
 
         // Similarly, set ACTION_EXIT to all hover targets and clear them.
         exitHoverTargets();
+        exitTooltipHoverTargets();
 
         // In case view is detached while transition is running
         mLayoutCalledWhileSuppressed = false;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1ff8fb0..e030e76 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3589,6 +3589,10 @@
                         mAttachInfo.mKeyDispatchState.reset();
                         mView.dispatchWindowFocusChanged(hasWindowFocus);
                         mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
+
+                        if (mAttachInfo.mTooltipHost != null) {
+                            mAttachInfo.mTooltipHost.hideTooltip();
+                        }
                     }
 
                     // Note: must be done after the focus change callbacks,
@@ -4206,6 +4210,10 @@
         private int processKeyEvent(QueuedInputEvent q) {
             final KeyEvent event = (KeyEvent)q.mEvent;
 
+            if (mAttachInfo.mTooltipHost != null) {
+                mAttachInfo.mTooltipHost.handleTooltipKey(event);
+            }
+
             // If the key's purpose is to exit touch mode then we consume it
             // and consider it handled.
             if (checkForLeavingTouchModeAndConsume(event)) {
@@ -4232,6 +4240,10 @@
                 ensureTouchMode(true);
             }
 
+            if (action == MotionEvent.ACTION_DOWN && mAttachInfo.mTooltipHost != null) {
+                mAttachInfo.mTooltipHost.hideTooltip();
+            }
+
             // Offset the scroll position.
             if (mCurScrollY != 0) {
                 event.offsetLocation(0, mCurScrollY);
@@ -4425,6 +4437,7 @@
             mAttachInfo.mHandlingPointerEvent = true;
             boolean handled = eventTarget.dispatchPointerEvent(event);
             maybeUpdatePointerIcon(event);
+            maybeUpdateTooltip(event);
             mAttachInfo.mHandlingPointerEvent = false;
             if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
                 mUnbufferedInputDispatch = true;
@@ -4512,6 +4525,27 @@
         return true;
     }
 
+    private void maybeUpdateTooltip(MotionEvent event) {
+        if (event.getPointerCount() != 1) {
+            return;
+        }
+        final int action = event.getActionMasked();
+        if (action != MotionEvent.ACTION_HOVER_ENTER
+                && action != MotionEvent.ACTION_HOVER_MOVE
+                && action != MotionEvent.ACTION_HOVER_EXIT) {
+            return;
+        }
+        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
+        if (manager.isEnabled() && manager.isTouchExplorationEnabled()) {
+            return;
+        }
+        if (mView == null) {
+            Slog.d(mTag, "maybeUpdateTooltip called after view was removed");
+            return;
+        }
+        mView.dispatchTooltipHoverEvent(event);
+    }
+
     /**
      * Performs synthesis of new input events from unhandled input events.
      */
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index c147895..eb0c44c 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -57,7 +57,9 @@
 @SystemApi
 public final class WebViewFactory {
 
-    private static final String CHROMIUM_WEBVIEW_FACTORY =
+    // visible for WebViewZygoteInit to look up the class by reflection and call preloadInZygote.
+    /** @hide */
+    public static final String CHROMIUM_WEBVIEW_FACTORY =
             "com.android.webview.chromium.WebViewChromiumFactoryProvider";
 
     private static final String CHROMIUM_WEBVIEW_FACTORY_METHOD = "create";
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index bc6e7b4..c206974 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -16,14 +16,19 @@
 
 package android.webkit;
 
+import android.app.LoadedApk;
 import android.content.pm.PackageInfo;
 import android.os.Build;
 import android.os.SystemService;
 import android.os.ZygoteProcess;
+import android.text.TextUtils;
 import android.util.Log;
 
+import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.TimeoutException;
 
 /** @hide */
@@ -122,11 +127,21 @@
         try {
             sZygote = new ZygoteProcess("webview_zygote", null);
 
-            String packagePath = sPackage.applicationInfo.sourceDir;
-            String libsPath = sPackage.applicationInfo.nativeLibraryDir;
+            // All the work below is usually done by LoadedApk, but the zygote can't talk to
+            // PackageManager or construct a LoadedApk since it's single-threaded pre-fork, so
+            // doesn't have an ActivityThread and can't use Binder.
+            // Instead, figure out the paths here, in the system server where we have access to
+            // the package manager. Reuse the logic from LoadedApk to determine the correct
+            // paths and pass them to the zygote as strings.
+            final List<String> zipPaths = new ArrayList<>(10);
+            final List<String> libPaths = new ArrayList<>(10);
+            LoadedApk.makePaths(null, sPackage.applicationInfo, zipPaths, libPaths);
+            final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
+            final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
+                    TextUtils.join(File.pathSeparator, zipPaths);
 
-            Log.d(LOGTAG, "Preloading package " + packagePath + " " + libsPath);
-            sZygote.preloadPackageForAbi(packagePath, libsPath, Build.SUPPORTED_ABIS[0]);
+            Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath);
+            sZygote.preloadPackageForAbi(zip, librarySearchPath, Build.SUPPORTED_ABIS[0]);
         } catch (Exception e) {
             Log.e(LOGTAG, "Error connecting to " + serviceName, e);
             sZygote = null;
diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java
index 11dd0e8..d968e3c 100644
--- a/core/java/com/android/internal/os/WebViewZygoteInit.java
+++ b/core/java/com/android/internal/os/WebViewZygoteInit.java
@@ -16,14 +16,17 @@
 
 package com.android.internal.os;
 
+import android.app.ApplicationLoaders;
 import android.net.LocalSocket;
 import android.os.Build;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.text.TextUtils;
 import android.util.Log;
+import android.webkit.WebViewFactory;
 
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
 
 /**
  * Startup class for the WebView zygote process.
@@ -52,7 +55,27 @@
 
         @Override
         protected boolean handlePreloadPackage(String packagePath, String libsPath) {
-            // TODO: Use preload information to setup the ClassLoader.
+            // Ask ApplicationLoaders to create and cache a classloader for the WebView APK so that
+            // our children will reuse the same classloader instead of creating their own.
+            // This enables us to preload Java and native code in the webview zygote process and
+            // have the preloaded versions actually be used post-fork.
+            ClassLoader loader = ApplicationLoaders.getDefault().createAndCacheWebViewClassLoader(
+                    packagePath, libsPath);
+
+            // Once we have the classloader, look up the WebViewFactoryProvider implementation and
+            // call preloadInZygote() on it to give it the opportunity to preload the native library
+            // and perform any other initialisation work that should be shared among the children.
+            try {
+                Class providerClass = Class.forName(WebViewFactory.CHROMIUM_WEBVIEW_FACTORY, true,
+                                                    loader);
+                Object result = providerClass.getMethod("preloadInZygote").invoke(null);
+                if (!((Boolean)result).booleanValue()) {
+                    Log.e(TAG, "preloadInZygote returned false");
+                }
+            } catch (ClassNotFoundException | NoSuchMethodException | SecurityException |
+                     IllegalAccessException | InvocationTargetException e) {
+                Log.e(TAG, "Exception while preloading package", e);
+            }
             return false;
         }
     }
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 594b6ab..c03bcdf 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -17,6 +17,8 @@
 package com.android.internal.os;
 
 import android.os.Process;
+import android.os.Trace;
+import android.util.BootTimingsTraceLog;
 import android.util.Slog;
 
 import dalvik.system.VMRuntime;
@@ -75,7 +77,8 @@
             }
 
             // Mimic system Zygote preloading.
-            ZygoteInit.preload();
+            ZygoteInit.preload(new BootTimingsTraceLog("WrapperInitTiming",
+                    Trace.TRACE_TAG_DALVIK));
 
             // Launch the application.
             String[] runtimeArgs = new String[args.length - 2];
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index e1118d8..cdd267e 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -36,11 +36,13 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.text.Hyphenator;
+import android.util.BootTimingsTraceLog;
 import android.util.EventLog;
 import android.util.Log;
 import android.webkit.WebViewFactory;
 import android.widget.TextView;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.InstallerConnection.InstallerException;
 
 import dalvik.system.DexFile;
@@ -106,20 +108,20 @@
     private static final int ROOT_UID = 0;
     private static final int ROOT_GID = 0;
 
-    static void preload() {
+    static void preload(BootTimingsTraceLog bootTimingsTraceLog) {
         Log.d(TAG, "begin preload");
-        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");
+        bootTimingsTraceLog.traceBegin("BeginIcuCachePinning");
         beginIcuCachePinning();
-        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
-        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
+        bootTimingsTraceLog.traceEnd(); // BeginIcuCachePinning
+        bootTimingsTraceLog.traceBegin("PreloadClasses");
         preloadClasses();
-        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
-        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
+        bootTimingsTraceLog.traceEnd(); // PreloadClasses
+        bootTimingsTraceLog.traceBegin("PreloadResources");
         preloadResources();
-        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
-        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
+        bootTimingsTraceLog.traceEnd(); // PreloadResources
+        bootTimingsTraceLog.traceBegin("PreloadOpenGL");
         preloadOpenGL();
-        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
+        bootTimingsTraceLog.traceEnd(); // PreloadOpenGL
         preloadSharedLibraries();
         preloadTextResources();
         // Ask the WebViewFactory to do any initialization that must run in the zygote process,
@@ -639,7 +641,13 @@
         }
 
         try {
-            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
+            // Report Zygote start time to tron
+            MetricsLogger.histogram(null, "boot_zygote_init", (int) SystemClock.uptimeMillis());
+
+            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
+            BootTimingsTraceLog bootTimingsTraceLog = new BootTimingsTraceLog(bootTimeTag,
+                    Trace.TRACE_TAG_DALVIK);
+            bootTimingsTraceLog.traceBegin("ZygoteInit");
             RuntimeInit.enableDdms();
             // Start profiling the zygote initialization.
             SamplingProfilerIntegration.start();
@@ -664,22 +672,23 @@
             }
 
             zygoteServer.registerServerSocket(socketName);
-            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
+            bootTimingsTraceLog.traceBegin("ZygotePreload");
             EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                 SystemClock.uptimeMillis());
-            preload();
+            preload(bootTimingsTraceLog);
             EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                 SystemClock.uptimeMillis());
-            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
+            bootTimingsTraceLog.traceEnd(); // ZygotePreload
 
             // Finish profiling the zygote initialization.
             SamplingProfilerIntegration.writeZygoteSnapshot();
 
             // Do an initial gc to clean up after startup
-            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
+            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
             gcAndFinalize();
-            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
+            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
 
+            bootTimingsTraceLog.traceEnd(); // ZygoteInit
             // Disable tracing so that forked processes do not inherit stale tracing tags from
             // Zygote.
             Trace.setTracingEnabled(false);
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index 4748e6f..7ee5170 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -268,6 +268,45 @@
     }
 
     /**
+     * Finds a suitable color such that there's enough contrast.
+     *
+     * @param color the color to start searching from.
+     * @param other the color to ensure contrast against. Assumed to be darker than {@param color}
+     * @param findFg if true, we assume {@param color} is a foreground, otherwise a background.
+     * @param minRatio the minimum contrast ratio required.
+     * @return a color with the same hue as {@param color}, potentially darkened to meet the
+     *          contrast ratio.
+     */
+    public static int findContrastColorAgainstDark(int color, int other, boolean findFg,
+            double minRatio) {
+        int fg = findFg ? color : other;
+        int bg = findFg ? other : color;
+        if (ColorUtilsFromCompat.calculateContrast(fg, bg) >= minRatio) {
+            return color;
+        }
+
+        double[] lab = new double[3];
+        ColorUtilsFromCompat.colorToLAB(findFg ? fg : bg, lab);
+
+        double low = lab[0], high = 100;
+        final double a = lab[1], b = lab[2];
+        for (int i = 0; i < 15 && high - low > 0.00001; i++) {
+            final double l = (low + high) / 2;
+            if (findFg) {
+                fg = ColorUtilsFromCompat.LABToColor(l, a, b);
+            } else {
+                bg = ColorUtilsFromCompat.LABToColor(l, a, b);
+            }
+            if (ColorUtilsFromCompat.calculateContrast(fg, bg) > minRatio) {
+                high = l;
+            } else {
+                low = l;
+            }
+        }
+        return ColorUtilsFromCompat.LABToColor(high, a, b);
+    }
+
+    /**
      * Finds a text color with sufficient contrast over bg that has the same hue as the original
      * color, assuming it is for large text.
      */
diff --git a/core/java/com/android/internal/view/TooltipPopup.java b/core/java/com/android/internal/view/TooltipPopup.java
new file mode 100644
index 0000000..4f48b96
--- /dev/null
+++ b/core/java/com/android/internal/view/TooltipPopup.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+public class TooltipPopup {
+    private final Context mContext;
+
+    private final View mContentView;
+    private final TextView mMessageView;
+
+    private final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
+    private final Rect mTmpDisplayFrame = new Rect();
+    private final int[] mTmpAnchorPos = new int[2];
+
+    public TooltipPopup(Context context) {
+        mContext = context;
+
+        mContentView = LayoutInflater.from(mContext).inflate(
+                com.android.internal.R.layout.tooltip, null);
+        mMessageView = (TextView) mContentView.findViewById(
+                com.android.internal.R.id.message);
+
+        mLayoutParams.setTitle(
+                mContext.getString(com.android.internal.R.string.tooltip_popup_title));
+        mLayoutParams.packageName = mContext.getOpPackageName();
+        mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
+        mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
+        mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
+        mLayoutParams.format = PixelFormat.TRANSLUCENT;
+        mLayoutParams.windowAnimations = com.android.internal.R.style.Animation_Tooltip;
+        mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+    }
+
+    public void show(View anchorView, int anchorX, int anchorY, CharSequence tooltipText) {
+        if (isShowing()) {
+            hide();
+        }
+
+        mMessageView.setText(tooltipText);
+
+        computePosition(anchorView, anchorX, anchorY, mLayoutParams);
+
+        WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
+        wm.addView(mContentView, mLayoutParams);
+    }
+
+    public void hide() {
+        if (!isShowing()) {
+            return;
+        }
+
+        WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
+        wm.removeView(mContentView);
+    }
+
+    public View getContentView() {
+        return mContentView;
+    }
+
+    public boolean isShowing() {
+        return mContentView.getParent() != null;
+    }
+
+    public void updateContent(CharSequence tooltipText) {
+        mMessageView.setText(tooltipText);
+    }
+
+    private void computePosition(View anchorView, int anchorX, int anchorY,
+            WindowManager.LayoutParams outParams) {
+        final int tooltipPreciseAnchorThreshold = mContext.getResources().getDimensionPixelOffset(
+                com.android.internal.R.dimen.tooltip_precise_anchor_threshold);
+
+        final int offsetX;
+        if (anchorView.getWidth() >= tooltipPreciseAnchorThreshold) {
+            // Wide view. Align the tooltip horizontally to the precise X position.
+            offsetX = anchorX;
+        } else {
+            // Otherwise anchor the tooltip to the view center.
+            offsetX = anchorView.getWidth() / 2;  // Center on the view horizontally.
+        }
+
+        final int offsetBelow;
+        final int offsetAbove;
+        if (anchorView.getHeight() >= tooltipPreciseAnchorThreshold) {
+            // Tall view. Align the tooltip vertically to the precise Y position.
+            offsetBelow = anchorY;
+            offsetAbove = anchorY;
+        } else {
+            // Otherwise anchor the tooltip to the view center.
+            offsetBelow = anchorView.getHeight();  // Place below the view in most cases.
+            offsetAbove = 0;  // Place above the view if the tooltip does not fit below.
+        }
+
+        outParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
+
+        final int tooltipOffset = mContext.getResources().getDimensionPixelOffset(
+                com.android.internal.R.dimen.tooltip_y_offset);
+
+        anchorView.getWindowVisibleDisplayFrame(mTmpDisplayFrame);
+        anchorView.getLocationInWindow(mTmpAnchorPos);
+        outParams.x = mTmpAnchorPos[0] + offsetX - mTmpDisplayFrame.width() / 2;
+        outParams.y = mTmpAnchorPos[1] + offsetBelow + tooltipOffset;
+
+        final int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
+        mContentView.measure(spec, spec);
+        final int tooltipHeight = mContentView.getMeasuredHeight();
+
+        if (outParams.y + tooltipHeight > mTmpDisplayFrame.height()) {
+            // The tooltip does not fit below the anchor point, show above instead.
+            outParams.y = mTmpAnchorPos[1] + offsetAbove - (tooltipOffset + tooltipHeight);
+        }
+    }
+}
diff --git a/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp b/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp
index 4b279f63..b23757e 100644
--- a/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp
+++ b/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp
@@ -22,256 +22,89 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
 
-#include "activity_recognition.h"
-
-
-// keep base connection data from the HAL
-static activity_recognition_module_t* sModule = NULL;
-static activity_recognition_device_t* sDevice = NULL;
-
-static jobject sCallbacksObject = NULL;
-static jmethodID sOnActivityChanged = NULL;
-
-
-static void check_and_clear_exceptions(JNIEnv* env, const char* method_name) {
-    if (!env->ExceptionCheck()) {
-        return;
-    }
-
-    ALOGE("An exception was thrown by '%s'.", method_name);
-    LOGE_EX(env);
-    env->ExceptionClear();
-}
-
-static jint attach_thread(JNIEnv** env) {
-    JavaVM* java_vm = android::AndroidRuntime::getJavaVM();
-    assert(java_vm != NULL);
-
-    JavaVMAttachArgs args = {
-        JNI_VERSION_1_6,
-        "ActivityRecognition HAL callback.",
-        NULL /* group */
-    };
-
-    jint result = java_vm->AttachCurrentThread(env, &args);
-    if (result != JNI_OK) {
-        ALOGE("Attach to callback thread failed: %d", result);
-    }
-
-    return result;
-}
-
-static jint detach_thread() {
-    JavaVM* java_vm = android::AndroidRuntime::getJavaVM();
-    assert(java_vm != NULL);
-
-    jint result = java_vm->DetachCurrentThread();
-    if (result != JNI_OK) {
-        ALOGE("Detach of callback thread failed: %d", result);
-    }
-
-    return result;
-}
-
-
-/**
- * Handle activity recognition events from HAL.
- */
-static void activity_callback(
-        const activity_recognition_callback_procs_t* procs,
-        const activity_event_t* events,
-        int count) {
-    if (sOnActivityChanged == NULL) {
-        ALOGE("Dropping activity_callback because onActivityChanged handler is null.");
-        return;
-    }
-
-    if (events == NULL || count <= 0) {
-        ALOGE("Invalid activity_callback. Count: %d, Events: %p", count, events);
-        return;
-    }
-
-    JNIEnv* env = NULL;
-    int result = attach_thread(&env);
-    if (result != JNI_OK) {
-        ALOGE("Unable to attach thread with JNI.");
-        return;
-    }
-
-    jclass event_class =
-            env->FindClass("android/hardware/location/ActivityRecognitionHardware$Event");
-    jmethodID event_ctor = env->GetMethodID(event_class, "<init>", "()V");
-    jfieldID activity_field = env->GetFieldID(event_class, "activity", "I");
-    jfieldID type_field = env->GetFieldID(event_class, "type", "I");
-    jfieldID timestamp_field = env->GetFieldID(event_class, "timestamp", "J");
-
-    jobjectArray events_array = env->NewObjectArray(count, event_class, NULL);
-    for (int i = 0; i < count; ++i) {
-        const activity_event_t* event = &events[i];
-        jobject event_object = env->NewObject(event_class, event_ctor);
-        env->SetIntField(event_object, activity_field, event->activity);
-        env->SetIntField(event_object, type_field, event->event_type);
-        env->SetLongField(event_object, timestamp_field, event->timestamp);
-        env->SetObjectArrayElement(events_array, i, event_object);
-        env->DeleteLocalRef(event_object);
-    }
-
-    env->CallVoidMethod(sCallbacksObject, sOnActivityChanged, events_array);
-    check_and_clear_exceptions(env, __FUNCTION__);
-
-    // TODO: ideally we'd let the HAL register the callback thread only once
-    detach_thread();
-}
-
-activity_recognition_callback_procs_t sCallbacks = {
-    activity_callback,
-};
+// #include "activity_recognition.h"
+// The activity recognition HAL is being deprecated. This means -
+//    i) Android framework code shall not depend on activity recognition
+//       being provided through the activity_recognition.h interface.
+//   ii) activity recognition HAL will not be binderized as the other HALs.
+//
 
 /**
  * Initializes the ActivityRecognitionHardware class from the native side.
  */
-static void class_init(JNIEnv* env, jclass clazz) {
-    // open the hardware module
-    int error = hw_get_module(
-            ACTIVITY_RECOGNITION_HARDWARE_MODULE_ID,
-            (const hw_module_t**) &sModule);
-    if (error != 0) {
-        ALOGE("Error hw_get_module: %d", error);
-        return;
-    }
-
-    error = activity_recognition_open(&sModule->common, &sDevice);
-    if (error != 0) {
-        ALOGE("Error opening device: %d", error);
-        return;
-    }
-
-    // get references to the Java provided methods
-    sOnActivityChanged = env->GetMethodID(
-            clazz,
-            "onActivityChanged",
-            "([Landroid/hardware/location/ActivityRecognitionHardware$Event;)V");
-    if (sOnActivityChanged == NULL) {
-        ALOGE("Error obtaining ActivityChanged callback.");
-        return;
-    }
-
-    // register callbacks
-    sDevice->register_activity_callback(sDevice, &sCallbacks);
+static void class_init(JNIEnv* /*env*/, jclass /*clazz*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
 }
 
 /**
  * Initializes and connect the callbacks handlers in the HAL.
  */
-static void initialize(JNIEnv* env, jobject obj) {
-    if (sCallbacksObject == NULL) {
-        sCallbacksObject = env->NewGlobalRef(obj);
-    } else {
-        ALOGD("Callbacks Object was already initialized.");
-    }
-
-    if (sDevice != NULL) {
-        sDevice->register_activity_callback(sDevice, &sCallbacks);
-    } else {
-        ALOGD("ActivityRecognition device not found during initialization.");
-    }
+static void initialize(JNIEnv* /*env*/, jobject /*obj*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
 }
 
 /**
  * De-initializes the ActivityRecognitionHardware from the native side.
  */
-static void release(JNIEnv* env, jobject obj) {
-    if (sDevice == NULL) {
-        return;
-    }
-
-    int error = activity_recognition_close(sDevice);
-    if (error != 0) {
-        ALOGE("Error closing device: %d", error);
-        return;
-    }
+static void release(JNIEnv* /*env*/, jobject /*obj*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
 }
 
 /**
  * Returns true if ActivityRecognition HAL is supported, false otherwise.
  */
-static jboolean is_supported(JNIEnv* env, jclass clazz) {
-    if (sModule != NULL && sDevice != NULL ) {
-        return JNI_TRUE;
-    }
+static jboolean is_supported(JNIEnv* /*env*/, jclass /*clazz*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
     return JNI_FALSE;
 }
 
 /**
  * Gets an array representing the supported activities.
  */
-static jobjectArray get_supported_activities(JNIEnv* env, jobject obj) {
-    if (sModule == NULL) {
-        return NULL;
-    }
-
-    char const* const* list = NULL;
-    int list_size = sModule->get_supported_activities_list(sModule, &list);
-    if (list_size <= 0 || list == NULL) {
-        return NULL;
-    }
-
-    jclass string_class = env->FindClass("java/lang/String");
-    if (string_class == NULL) {
-        ALOGE("Unable to find String class for supported activities.");
-        return NULL;
-    }
-
-    jobjectArray string_array = env->NewObjectArray(list_size, string_class, NULL);
-    if (string_array == NULL) {
-        ALOGE("Unable to create string array for supported activities.");
-        return NULL;
-    }
-
-    for (int i = 0; i < list_size; ++i) {
-        const char* string_ptr = const_cast<const char*>(list[i]);
-        jstring string = env->NewStringUTF(string_ptr);
-        env->SetObjectArrayElement(string_array, i, string);
-    }
-
-    return string_array;
+static jobjectArray get_supported_activities(JNIEnv* /*env*/, jobject /*obj*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+    return NULL;
 }
 
 /**
  * Enables a given activity event to be actively monitored.
  */
 static int enable_activity_event(
-        JNIEnv* env,
-        jobject obj,
-        jint activity_handle,
-        jint event_type,
-        jlong report_latency_ns) {
-    return sDevice->enable_activity_event(
-            sDevice,
-            (uint32_t) activity_handle,
-            (uint32_t) event_type,
-            report_latency_ns);
+        JNIEnv* /*env*/,
+        jobject /*obj*/,
+        jint /*activity_handle*/,
+        jint /*event_type*/,
+        jlong /*report_latency_ns*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+    return android::NO_INIT;
 }
 
 /**
  * Disables a given activity event from being actively monitored.
  */
 static int disable_activity_event(
-        JNIEnv* env,
-        jobject obj,
-        jint activity_handle,
-        jint event_type) {
-    return sDevice->disable_activity_event(
-            sDevice,
-            (uint32_t) activity_handle,
-            (uint32_t) event_type);
+        JNIEnv* /*env*/,
+        jobject /*obj*/,
+        jint /*activity_handle*/,
+        jint /*event_type*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+    return android::NO_INIT;
 }
 
 /**
  * Request flush for al batch buffers.
  */
-static int flush(JNIEnv* env, jobject obj) {
-    return sDevice->flush(sDevice);
+static int flush(JNIEnv* /*env*/, jobject /*obj*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+    return android::NO_INIT;
 }
 
 
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index fbccfd5..4391d93 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -16,26 +16,26 @@
 
 #include "context_hub.h"
 
+#undef LOG_NDEBUG
+#undef LOG_TAG
 #define LOG_NDEBUG 0
 #define LOG_TAG "ContextHubService"
 
 #include <inttypes.h>
 #include <jni.h>
-#include <mutex>
-#include <string.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-
-// TOOD: On master, alphabetize these and move <mutex> into this
-//     grouping.
-#include <chrono>
-#include <unordered_map>
-#include <queue>
+#include <string.h>
 
 #include <android-base/macros.h>
 #include <cutils/log.h>
 
+#include <chrono>
+#include <mutex>
+#include <queue>
+#include <unordered_map>
+
 #include "JNIHelp.h"
 #include "core_jni_helpers.h"
 
@@ -1180,7 +1180,6 @@
     }
 
     if (setAddressSuccess && hubId >= 0) {
-        ALOGD("Asking HAL to remove app");
         retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg);
     } else {
       ALOGD("Could not find app instance %" PRId32 " on hubHandle %" PRId32
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index 5dace6b..8844fb0 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -220,6 +220,11 @@
     }
 }
 
+static void SystemProperties_report_sysprop_change(JNIEnv /**env*/, jobject /*clazz*/)
+{
+    report_sysprop_change();
+}
+
 static const JNINativeMethod method_table[] = {
     { "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
       (void*) SystemProperties_getS },
@@ -235,6 +240,8 @@
       (void*) SystemProperties_set },
     { "native_add_change_callback", "()V",
       (void*) SystemProperties_add_change_callback },
+    { "native_report_sysprop_change", "()V",
+      (void*) SystemProperties_report_sysprop_change },
 };
 
 int register_android_os_SystemProperties(JNIEnv *env)
diff --git a/core/res/res/anim/tooltip_enter.xml b/core/res/res/anim/tooltip_enter.xml
new file mode 100644
index 0000000..7eceb4c
--- /dev/null
+++ b/core/res/res/anim/tooltip_enter.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+        android:interpolator="@interpolator/decelerate_quad"
+        android:fromAlpha="0.0" android:toAlpha="1.0"
+        android:duration="@android:integer/config_tooltipAnimTime" />
diff --git a/core/res/res/anim/tooltip_exit.xml b/core/res/res/anim/tooltip_exit.xml
new file mode 100644
index 0000000..e346ca9
--- /dev/null
+++ b/core/res/res/anim/tooltip_exit.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+        android:interpolator="@interpolator/accelerate_quad"
+        android:fromAlpha="1.0" android:toAlpha="0.0"
+        android:duration="@android:integer/config_tooltipAnimTime" />
diff --git a/core/res/res/drawable/tooltip_frame.xml b/core/res/res/drawable/tooltip_frame.xml
new file mode 100644
index 0000000..14130c8
--- /dev/null
+++ b/core/res/res/drawable/tooltip_frame.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <solid android:color="?attr/tooltipBackgroundColor" />
+    <corners android:radius="@dimen/tooltip_corner_radius" />
+</shape>
\ No newline at end of file
diff --git a/core/res/res/layout/tooltip.xml b/core/res/res/layout/tooltip.xml
new file mode 100644
index 0000000..0aa6a87
--- /dev/null
+++ b/core/res/res/layout/tooltip.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@android:id/message"
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/tooltip_height"
+        android:layout_margin="@dimen/tooltip_margin"
+        android:paddingStart="@dimen/tooltip_horizontal_padding"
+        android:paddingEnd="@dimen/tooltip_horizontal_padding"
+        android:gravity="center"
+        android:background="?android:attr/tooltipFrameBackground"
+        android:textAppearance="@style/TextAppearance.Tooltip"
+        android:textColor="?android:attr/tooltipForegroundColor"
+        android:singleLine="true"
+        android:ellipsize="end"
+    />
+
+</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 5ca9f43..e43f1ba 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Mediavolume"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Kennisgewing-volume"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Verstekluitoon"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Verstekluitoon (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Geen"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Luitone"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Onbekende luitoon"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi netwerke beskikbaar</item>
       <item quantity="one">Wi-Fi-netwerk beskikbaar</item>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 18fc6dd..af8c592 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"የማህደረ መረጃ ክፍልፍል"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"የማሳወቂያ ክፍልፍል"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"ነባሪ የስልክ ላይ ጥሪ"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>) ነባሪ የስልክ ላይ ጥሪ"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"ምንም"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"ጥሪ ድምፆች"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"ያልታወቀ የስልክ ጥሪ ድምፅ"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">የWi-Fi አውታረ መረቦች አሉ</item>
       <item quantity="other">የWi-Fi አውታረ መረቦች አሉ</item>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 3451bcc..b3c24e5 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1151,10 +1151,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"مستوى صوت الوسائط"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"مستوى صوت الإشعار"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"نغمة الرنين الافتراضية"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"نغمة الرنين الافتراضية (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"لا شيء"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"نغمات الرنين"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"نغمة رنين غير معروفة"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="zero">‏لا تتوفر أية شبكات Wi-Fi</item>
       <item quantity="two">‏تتوفر شبكتا Wi-Fi</item>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 1f0d164..7e9c508 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Media həcmi"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Bildiriş səsi"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Defolt rinqton"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Defolt rinqton (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Heç biri"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Zəng səsləri"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Naməlum rinqton"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Əlçatan Wi-Fi şəbəkələri</item>
       <item quantity="one">Əlçatan Wi-Fi şəbəkəsi</item>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 2509eae..6caf561 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1082,10 +1082,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Jačina zvuka medija"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Jačina zvuka obaveštenja"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Podrazumevani zvuk zvona"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Podrazumevani zvuk zvona (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Bez zvuka"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Zvukovi zvona"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Nepoznati zvuk zvona"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Wi-Fi mreže su dostupne</item>
       <item quantity="few">Wi-Fi mreže su dostupne</item>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index f5f1e62..c076db2 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -1105,10 +1105,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Гучнасць прайгравальніка"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Гучнасць апавяшчэнняў"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Стандартны рынгтон"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Стандартны рынгтон (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Няма"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Рынгтоны"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Невядомы рынгтон"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">сетка Wi-Fi даступная</item>
       <item quantity="few">сеткі Wi-Fi даступныя</item>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index f6eb810..2d6bdb2 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Сила на звука"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Сила на звука при известие"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Стандартна мелодия"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Стандартна мелодия (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Без"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодии"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Неизвестна мелодия"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Има достъпни Wi-Fi мрежи</item>
       <item quantity="one">Има достъпна Wi-Fi мрежа</item>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 993d49b..21b737a 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"মিডিয়ার ভলিউম"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"বিজ্ঞপ্তির ভলিউম"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"ডিফল্ট রিংটোন"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"ডিফল্ট রিংটোন (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"কোনো কিছুই নয়"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"রিংটোনগুলি"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"অজানা রিংটোন"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">ওয়াই-ফাই নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
       <item quantity="other">ওয়াই-ফাই নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index 7cb46fe..80ee407 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -1084,10 +1084,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Jačina zvuka za medijske sadržaje"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Jačina zvuka za obavještenja"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Zadana melodija zvona"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Zadano zvono (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Bez zvuka"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Melodije zvona"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Nepoznato zvono"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Wi-Fi mreže su dostupne</item>
       <item quantity="few">Wi-Fi mreže su dostupne</item>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 522efc5..35b2918 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volum de multimèdia"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volum de notificació"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"So predeterminat"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"So predeterminat (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Cap"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Sons"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"So desconegut"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Xarxes Wi-Fi disponibles</item>
       <item quantity="one">Xarxa Wi-Fi disponible</item>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 0e6ba82..95a6728 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1105,10 +1105,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Hlasitost médií"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Hlasitost oznámení"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Výchozí vyzváněcí tón"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Výchozí tón (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Žádný"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Vyzváněcí tóny"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Neznámý vyzváněcí tón"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="few">K dispozici jsou sítě Wi-Fi</item>
       <item quantity="many">K dispozici jsou sítě Wi-Fi</item>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 628f9bb..a628e42 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Medielydstyrke"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Lydstyrke for meddelelser"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standardringetone"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Standardringetone (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ringetoner"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Ukendt ringetone"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Tilgængelige Wi-Fi-netværk</item>
       <item quantity="other">Tilgængelige Wi-Fi-netværk</item>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 9d8c98b..86f2070 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Medienlautstärke"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Benachrichtigungslautstärke"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standard-Klingelton"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Standard-Klingelton (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ohne"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Klingeltöne"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Unbekannter Klingelton"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">WLAN-Netzwerke verfügbar</item>
       <item quantity="one">WLAN-Netzwerk verfügbar</item>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 4283827..4ce3a1f 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Ένταση ήχου πολυμέσων"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Ένταση ήχου ειδοποιήσεων"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Προεπιλεγμένος ήχος κλήσης"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Προεπ. ήχος (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Κανένας"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ήχοι κλήσης"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Άγνωστος ήχος κλήσης"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Υπάρχουν διαθέσιμα δίκτυα Wi-Fi</item>
       <item quantity="one">Υπάρχει διαθέσιμο δίκτυο Wi-Fi</item>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 38f2b88..72c1271 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Media volume"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Notification volume"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Default ringtone"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Default ringtone (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"None"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ringtones"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Unknown ringtone"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi networks available</item>
       <item quantity="one">Wi-Fi network available</item>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 38f2b88..72c1271 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Media volume"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Notification volume"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Default ringtone"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Default ringtone (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"None"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ringtones"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Unknown ringtone"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi networks available</item>
       <item quantity="one">Wi-Fi network available</item>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 38f2b88..72c1271 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Media volume"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Notification volume"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Default ringtone"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Default ringtone (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"None"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ringtones"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Unknown ringtone"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi networks available</item>
       <item quantity="one">Wi-Fi network available</item>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 1277acc..738af8c 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volumen de los medios"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volumen de notificación"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Tono predeterminado"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Tono predeterminado (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ninguno"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Tonos de llamada"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Tono de llamada desconocido"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">redes de Wi-Fi disponibles</item>
       <item quantity="one">red de Wi-Fi disponible</item>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index fa03897..3c2915d 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volumen multimedia"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volumen de notificaciones"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Tono por defecto"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Tono predeterminado (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ninguno"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Tonos"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Tono desconocido"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Redes Wi-Fi disponibles</item>
       <item quantity="one">Red Wi-Fi disponible</item>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index d7ee50c..96b060f 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Meediumi helitugevus"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Teatise helitugevus"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Vaikehelin"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Vaikehelin (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Puudub"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Helinad"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Tundmatu helin"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">WiFi-võrgud on saadaval</item>
       <item quantity="one">WiFi-võrk on saadaval</item>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index e7f3f02..6ccd864 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Euskarriaren bolumena"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Jakinarazpenen bolumena"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Tonu lehenetsia"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Tonu lehenetsia (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Bat ere ez"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Tonuak"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Tonu ezezaguna"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi sareak erabilgarri</item>
       <item quantity="one">Wi-Fi sarea erabilgarri</item>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 374183f..e8e61f4 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"میزان صدای رسانه"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"میزان صدای اعلان"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"آهنگ زنگ پیش‌فرض"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"آهنگ زنگ پیش‌فرض (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"هیچ‌کدام"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"آهنگ‌های زنگ"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"آهنگ زنگ ناشناس"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">‏شبکه Wi-Fi در دسترس</item>
       <item quantity="other">‏شبکه‌ Wi-Fi در دسترس</item>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 9b6d57c..dbfd8ba 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Median äänenvoimakkuus"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Ilmoituksen äänenvoimakkuus"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Oletussoittoääni"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Oletussoittoääni (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ei mitään"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Soittoäänet"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Tuntematon soittoääni"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi-verkkoja käytettävissä</item>
       <item quantity="one">Wi-Fi-verkko käytettävissä</item>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 034b291..501627d 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volume"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume des notifications"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Sonnerie par défaut"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Sonnerie par défaut (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Aucune"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Sonneries"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Sonnerie inconnue"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Réseau Wi-Fi à proximité</item>
       <item quantity="other">Réseaux Wi-Fi à proximité</item>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 1e5f6a1..ccff4f3 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volume"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume des notifications"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Sonnerie par défaut"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Sonnerie par défaut (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Aucune"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Sonneries"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Sonnerie inconnue"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Réseau Wi-Fi disponible</item>
       <item quantity="other">Réseaux Wi-Fi disponibles</item>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 704667a..89a9471 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volume dos elementos multimedia"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume das notificacións"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Ton de chamada predeterminado"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Ton de chamada predeterminado (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ningún"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Tons de chamada"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Ton de chamada descoñecido"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Redes wifi dispoñibles</item>
       <item quantity="one">Rede wifi dispoñible</item>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index cd3e7be..cbb0d9e4a4 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"મીડિયા વોલ્યુમ"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"સૂચના વૉલ્યૂમ"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"ડિફોલ્ટ રિંગટોન"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"ડિફોલ્ટ રિંગટોન (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"કોઈ નહીં"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"રિંગટોન્સ"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"અજાણ રિંગટોન"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Wi-Fi નેટવર્ક્સ ઉપલબ્ધ</item>
       <item quantity="other">Wi-Fi નેટવર્ક્સ ઉપલબ્ધ</item>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index c8b3256..e833052 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -347,14 +347,14 @@
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"ऐप्स को इनकमिंग और आउटगोइंग कॉल के डेटा सहित, आपके फ़ोन का कॉल लॉग संशोधित करने देता है. दुर्भावनापूर्ण ऐप्स आपके कॉल लॉग को मिटाने या संशोधित करने के लिए इसका उपयोग कर सकते हैं."</string>
     <string name="permlab_bodySensors" msgid="4683341291818520277">"शरीर संवेदक एक्सेस करें (जैसे हृदय गति मॉनीटर)"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"ऐप को आपकी शारीरिक स्‍थिति, जैसे आपकी हृदय गति पर नज़र रखने वाले संवेदकों का डेटा एक्‍सेस करने देती है."</string>
-    <string name="permlab_readCalendar" msgid="5972727560257612398">"केलैंडर ईवेंट के साथ-साथ गोपनीय जानकारी पढ़ें"</string>
+    <string name="permlab_readCalendar" msgid="5972727560257612398">"केलैंडर इवेंट के साथ-साथ गोपनीय जानकारी पढ़ें"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"ऐप्स  को मित्रों या सहकर्मियों के कैलेंडर इवेंट सहित, आपके टेबलेट पर संग्रहीत कैलेंडर इवेंट पढ़ने देता है. इससे निजता या संवेदनशीलता पर ध्यान दिए बिना, ऐप्स  आपके कैलेंडर डेटा को साझा कर सकता है या सहेज सकता है."</string>
-    <string name="permdesc_readCalendar" product="tv" msgid="3191352452242394196">"ऐप को, मित्रों और सहकर्मियों के कैलेंडर ईवेंट सहित, आपके टीवी पर संग्रहीत सभी कैलेंडर ईवेंट पढ़ने देती है. इससे ऐप को निजता या संवेदनशीलता पर ध्‍यान दिए बिना, आपका कैलेडर डेटा साझा करने या सहेजने की अनुमति मिल जाती है."</string>
+    <string name="permdesc_readCalendar" product="tv" msgid="3191352452242394196">"ऐप को, मित्रों और सहकर्मियों के कैलेंडर इवेंट सहित, आपके टीवी पर संग्रहीत सभी कैलेंडर इवेंट पढ़ने देती है. इससे ऐप को निजता या संवेदनशीलता पर ध्‍यान दिए बिना, आपका कैलेडर डेटा साझा करने या सहेजने की अनुमति मिल जाती है."</string>
     <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"ऐप्स  को मित्रों या सहकर्मियों के कैलेंडर इवेंट सहित, आपके फ़ोन पर संग्रहीत कैलेंडर इवेंट पढ़ने देता है. इससे निजता या संवेदनशीलता पर ध्यान दिए बिना, ऐप्स  आपके कैलेंडर डेटा को साझा कर सकता है या सहेज सकता है."</string>
-    <string name="permlab_writeCalendar" msgid="8438874755193825647">"अपनी जानकारी के बि‍ना कैलेंडर ईवेंट जोड़ें या संशोधि‍त करें और अति‍थि‍यों को ईमेल भेजें"</string>
-    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"ऐप्स  को मित्रों या सहकर्मियों के ईवेंट के साथ ही वे ईवेंट जोड़ने, निकालने, बदलने देता है जिन्हें आप अपने टेबलेट पर संशोधित कर सकते हैं. इससे ऐप्स ,अपनी जानकारी के बिना उन संदेशों को भेज सकता है जो कैलेंडर स्वामियों की ओर से आते दिखाई देते हैं, या ईवेंट संशोधित कर सकता है."</string>
-    <string name="permdesc_writeCalendar" product="tv" msgid="1273290605500902507">"ऐप को ऐसे ईवेंट जोड़ने, निकालने, बदलने देती है जिन्हें आप अपने डिवाइस पर बदल सकते हैं, जिनमें मित्रों या सहकर्मियों के ईवेंट शामिल हैं. इससे ऐप ऐसे संदेश भेज सकता है जो कैलेंडर स्वामी से आते हुए प्रतीत होते हैं या ऐप स्वामी की जानकारी के बिना ईवेंट बदल सकता है."</string>
-    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"ऐप्स  को मित्रों या सहकर्मियों के ईवेंट के साथ ही वे ईवेंट जोड़ने, निकालने, बदलने देता है जिन्हें आप अपने फ़ोन पर संशोधित कर सकते हैं. इससे ऐप्स , अपनी जानकारी के बिना उन संदेशों को भेज सकता है जो कैलेंडर स्वामियों की ओर से आते दिखाई देते हैं, या ईवेंट संशोधित कर सकता है."</string>
+    <string name="permlab_writeCalendar" msgid="8438874755193825647">"अपनी जानकारी के बि‍ना कैलेंडर इवेंट जोड़ें या संशोधि‍त करें और अति‍थि‍यों को ईमेल भेजें"</string>
+    <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"ऐप्स  को मित्रों या सहकर्मियों के इवेंट के साथ ही वे इवेंट जोड़ने, निकालने, बदलने देता है जिन्हें आप अपने टेबलेट पर संशोधित कर सकते हैं. इससे ऐप्स ,अपनी जानकारी के बिना उन संदेशों को भेज सकता है जो कैलेंडर स्वामियों की ओर से आते दिखाई देते हैं, या इवेंट संशोधित कर सकता है."</string>
+    <string name="permdesc_writeCalendar" product="tv" msgid="1273290605500902507">"ऐप को ऐसे इवेंट जोड़ने, निकालने, बदलने देती है जिन्हें आप अपने डिवाइस पर बदल सकते हैं, जिनमें मित्रों या सहकर्मियों के इवेंट शामिल हैं. इससे ऐप ऐसे संदेश भेज सकता है जो कैलेंडर स्वामी से आते हुए प्रतीत होते हैं या ऐप स्वामी की जानकारी के बिना इवेंट बदल सकता है."</string>
+    <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"ऐप्स  को मित्रों या सहकर्मियों के इवेंट के साथ ही वे इवेंट जोड़ने, निकालने, बदलने देता है जिन्हें आप अपने फ़ोन पर संशोधित कर सकते हैं. इससे ऐप्स , अपनी जानकारी के बिना उन संदेशों को भेज सकता है जो कैलेंडर स्वामियों की ओर से आते दिखाई देते हैं, या इवेंट संशोधित कर सकता है."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"अतिरिक्त स्‍थान प्रदाता आदेशों में पहुंचे"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ऐप्स को अतिरिक्त स्थान प्रदाता आदेशों पर पहुंचने देती है. इससे ऐप्स GPS या अन्य स्थान स्रोतों के संचालन में अवरोध पहुंचा सकता है."</string>
     <string name="permlab_accessFineLocation" msgid="251034415460950944">"सटीक स्थान एक्सेस करें (GPS और नेटवर्क-आधारित)"</string>
@@ -459,7 +459,7 @@
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"समन्‍वयन बंद या चालू टॉगल करें"</string>
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"ऐप्स  को किसी खाते की समन्वयन सेटिंग संशोधित करने देता है. उदाहरण के लिए, इसका उपयोग लोग ऐप्स  का समन्‍वयन किसी खाते से सक्षम करने में हो सकता है."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"समन्वयन आंकड़े पढ़ें"</string>
-    <string name="permdesc_readSyncStats" msgid="1510143761757606156">"ऐप्स  को किसी खाते के समन्वयन आंकड़े, साथ ही समन्‍वयित ईवेंट का इतिहास और समन्‍वयित डेटा की मात्रा पढ़ने देता है."</string>
+    <string name="permdesc_readSyncStats" msgid="1510143761757606156">"ऐप्स  को किसी खाते के समन्वयन आंकड़े, साथ ही समन्‍वयित इवेंट का इतिहास और समन्‍वयित डेटा की मात्रा पढ़ने देता है."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"अपने USB मेमोरी की सामग्री पढ़ें"</string>
     <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"अपने SD कार्ड की सामग्री पढ़ें"</string>
     <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"एप्‍लिकेशन को आपके USB मेमोरी की सामग्री पढ़ने की अनुमति देता है."</string>
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"मीडिया वॉल्‍यूम"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"नोटिफिकेशन वॉल्‍यूम"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"डिफ़ॉल्‍ट रिंगटोन"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"डिफ़ॉल्‍ट रिंगटोन (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"कोई नहीं"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"रिंगटोन"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"अज्ञात रिंगटोन"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">वाई-फ़ाई नेटवर्क उपलब्‍ध</item>
       <item quantity="other">वाई-फ़ाई नेटवर्क उपलब्‍ध</item>
@@ -1614,7 +1620,7 @@
     <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"बंद रहने का समय"</string>
     <string name="zen_mode_default_weeknights_name" msgid="3081318299464998143">"सप्ताह की रात"</string>
     <string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"सप्ताहांत"</string>
-    <string name="zen_mode_default_events_name" msgid="8158334939013085363">"ईवेंट"</string>
+    <string name="zen_mode_default_events_name" msgid="8158334939013085363">"इवेंट"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> द्वारा म्यूट किया गया"</string>
     <string name="system_error_wipe_data" msgid="6608165524785354962">"आपके डिवाइस के साथ कोई आंतरिक त्रुटि हुई और यह तब तक अस्‍थिर रह सकता है, जब तक आप फ़ैक्‍टरी डेटा रीसेट नहीं करते हैं."</string>
     <string name="system_error_manufacturer" msgid="8086872414744210668">"आपके डिवाइस के साथ कोई आंतरिक त्रुटि हुई. विवरणों के लिए अपने निर्माता से संपर्क करें."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 3fc3346..e811b94 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1082,10 +1082,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Glasnoća medija"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Glasnoća obavijesti"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Zadana melodija zvona"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Zadana melodija zvona (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ništa"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Melodije zvona"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Nepoznata melodija zvona"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Dostupne su Wi-Fi mreže</item>
       <item quantity="few">Dostupne su Wi-Fi mreže</item>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 825672b..b0ce160 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Média hangereje"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Értesítés hangereje"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Alapértelmezett csengőhang"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Alap csengőhang (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Egyik sem"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Csengőhangok"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Ismeretlen csengőhang"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi hálózatok érhetők el</item>
       <item quantity="one">Van elérhető Wi-Fi hálózat</item>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index af7aaaf..2ba22af 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Մեդիա ձայնի բարձրություն"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Ծանուցումների ձայնի ուժգնությունը"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Կանխադրված զանգերանգ"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Կանխադրված զանգերանգ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ոչ մեկը"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Զանգերանգներ"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Անհայտ զանգերանգ"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Հասանելի են Wi-Fi ցանցեր</item>
       <item quantity="other">Հասանելի են Wi-Fi ցանցեր</item>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 05fe8d0..09223cd 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volume media"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume pemberitahuan"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Nada dering default"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Nada dering default (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Tidak Ada"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Nada dering"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Nada dering tidak dikenal"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Jaringan Wi-Fi tersedia</item>
       <item quantity="one">Jaringan Wi-Fi tersedia</item>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index cd41f51..105a647 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Hljóðstyrkur efnisspilunar"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Hljóðstyrkur tilkynninga"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Sjálfgefinn hringitónn"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Sjálfg. hringitónn (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ekkert"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Hringitónar"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Óþekktur hringitónn"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Wi-Fi net í boði</item>
       <item quantity="other">Wi-Fi net í boði</item>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index ec7f8f9..564472e 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volume contenuti multimediali"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume notifiche"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Suoneria predefinita"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Suoneria predefinita (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Nessuna"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Suonerie"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Suoneria sconosciuta"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Reti Wi-Fi disponibili</item>
       <item quantity="one">Rete Wi-Fi disponibile</item>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 290a31f..d4b9bf1 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1105,10 +1105,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"עוצמת קול של מדיה"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"עוצמת קול של התראות"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"רינגטון ברירת מחדל"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"רינגטון ברירת מחדל (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"ללא"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"רינגטונים"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"רינגטון לא ידוע"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="two">‏יש רשתות Wi-Fi זמינות</item>
       <item quantity="many">‏יש רשתות Wi-Fi זמינות</item>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 02736ec..e2432f1 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"メディアの音量"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"プリセット着信音"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"端末の基本着信音(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"なし"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"着信音"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"不明な着信音"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">複数のWi-Fiネットワークが利用できます</item>
       <item quantity="one">Wi-Fiネットワークが利用できます</item>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 1e34347..5e069b6 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"მედიის ხმა"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"შეტყობინების ხმა"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"ნაგულისხმევი ზარი"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"ნაგულის.ზარი (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"არც ერთი"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"ზარები"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"უცნობი ზარი"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">ხელმისაწვდომია Wi-Fi ქსელები</item>
       <item quantity="one">ხელმისაწვდომია Wi-Fi ქსელი</item>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 9a227c4..729f726 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Meдиа дыбысының қаттылығы"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Хабар дыбысының қаттылығы"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Әдепкі рингтон"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Әдепкі рингтон (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ешқандай"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Қоңырау әуендері"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Белгісіз қоңырау әуені"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi желілері қол жетімді</item>
       <item quantity="one">Wi-Fi желісі қол жетімді</item>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 2491f82..c3e939e 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1061,10 +1061,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"កម្រិត​សំឡេង​មេឌៀ"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"កម្រិត​សំឡេង​ការ​ជូន​ដំណឹង"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"សំឡេង​រោទ៍​លំនាំដើម"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"សំឡេង​រោទ៍​លំនាំដើម (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"គ្មាន"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"សំឡេង​រោទ៍"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"សំឡេង​រោទ៍​មិន​ស្គាល់"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">មានបណ្តាញ Wi-Fi</item>
       <item quantity="one">មានបណ្តាញ Wi-Fi</item>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 732a321..7f80a29 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"ಮೀಡಿಯಾ ವಾಲ್ಯೂಮ್"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"ಅಧಿಸೂಚನೆಯ ವಾಲ್ಯೂಮ್"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"ಡಿಫಾಲ್ಟ್ ರಿಂಗ್‌ಟೋನ್"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"ಡಿಫಾಲ್ಟ್ ರಿಂಗ್‌ಟೋನ್ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"ಯಾವುದೂ ಇಲ್ಲ"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"ರಿಂಗ್‌ಟೋನ್‌ಗಳು"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"ಅಪರಿಚಿತ ರಿಂಗ್‌ಟೋನ್"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿವೆ</item>
       <item quantity="other">ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿವೆ</item>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 6e1012a..444c83d 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"미디어 볼륨"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"알림 볼륨"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"기본 벨소리"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"기본 벨소리(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"없음"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"벨소리"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"알 수 없는 벨소리"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi 네트워크 사용 가능</item>
       <item quantity="one">Wi-Fi 네트워크 사용 가능</item>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 7a48ae5..2b592bd 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Медиа үнүнүн деңгээли"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Эскертме үнүнүн деңгээли"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Демейки рингтон"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Демейки рингтон (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Эч бир"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ринтондор"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Белгисиз рингтон"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi тармагы жеткиликтүү</item>
       <item quantity="one">Wi-Fi тармагы жеткиликтүү</item>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 26c9053..3a96743 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"ລະດັບສຽງຂອງສື່"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"ລະດັບສຽງການແຈ້ງເຕືອນ"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"ຣິງໂທນເລີ່ມຕົ້ນ"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"ຣິງໂທນເລີ່ມຕົ້ນ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"ບໍ່ມີ"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"ຣິງໂທນ"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"ຣິງໂທນທີ່ບໍ່ຮູ້ຈັກ"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">ເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
       <item quantity="one">ເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index c7806f2..d60a010 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1105,10 +1105,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Medijos garsumas"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Pranešimo apimtis"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Numatytasis skambėjimo tonas"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Numatytasis skambėjimo tonas („<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>“)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Nėra"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Skambėjimo tonai"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Nežinomas skambėjimo tonas"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Pasiekiami „Wi-Fi“ tinklai</item>
       <item quantity="few">Pasiekiami „Wi-Fi“ tinklai</item>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 6ea7d6b..7afb2ce 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1082,10 +1082,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Multivides skaļums"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Paziņojumu skaļums"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Noklusējuma zvana signāls"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Noklusējuma zvana signāls (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Nav"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Zvana signāli"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Nezināms zvana signāls"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="zero">Pieejami Wi-Fi tīkli</item>
       <item quantity="one">Pieejami Wi-Fi tīkli</item>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 3f228203..139e02a 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Јачина на звук на медиуми"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Јачина на звук на известување"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Стандардна мелодија"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Стандардна мелодија (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ниедна"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодии"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Непозната мелодија"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Wi-Fi мрежи се достапни</item>
       <item quantity="other">Wi-Fi мрежи се достапни</item>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index beb6a67..fc3eb40 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"മീഡിയ വോളിയം"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"അറിയിപ്പ് വോളിയം"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"ഡിഫോൾട്ട് റിംഗ്‌ടോൺ"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"ഡിഫോൾട്ട് റിംഗ്‌ടോൺ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"ഒന്നും വേണ്ട"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"റിംഗ്ടോണുകൾ"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"അജ്ഞാത റിംഗ്‌ടോൺ"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">വൈഫൈ നെറ്റ്‌വർക്കുകൾ ലഭ്യമാണ്</item>
       <item quantity="one">വൈഫൈ നെറ്റ്‌വർക്ക് ലഭ്യമാണ്</item>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index bd80f84..2faf163 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Медиа дууны хэмжээ"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Мэдэгдлийн дууны хэмжээ"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Үндсэн хонхны ая"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Үндсэн хонхны ая (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Алийг нь ч биш"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Хонхны ая"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Үл мэдэгдэх хонхны ая"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi сүлжээ ашиглах боломжтой</item>
       <item quantity="one">Wi-Fi сүлжээ ашиглах боломжтой</item>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 758b21b..99465cc 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"मीडिया व्हॉल्यूम"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"सूचना व्हॉल्यूम"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"डीफॉल्ट रिंगटोन"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"डीफॉल्ट रिंगटोन (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"काहीही नाही"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"रिंगटोन"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"अज्ञात रिंगटोन"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">वाय-फाय नेटवर्क उपलब्ध</item>
       <item quantity="other">वाय-फाय नेटवर्क उपलब्ध</item>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 60330e5..1e7e281 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Kelantangan media"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Kelantangan pemberitahuan"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Nada dering lalai"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Nada dering lalai (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Tiada"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Nada dering"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Nada dering tidak diketahui"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Rangkaian Wi-Fi tersedia</item>
       <item quantity="one">Rangkaian Wi-Fi tersedia</item>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index c18ff7f..99d6423 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"မီဒီယာအသံအတိုးအကျယ်"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"အကြောင်းကြားသံအတိုးအကျယ်"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"မူရင်းမြည်သံ"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"မူရင်းမြည်သံ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"တစ်ခုမှမဟုတ်"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"မြည်သံများ"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"မသိသောမြည်သံ"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi ကွန်ယက်များရရှိနိုင်သည်</item>
       <item quantity="one">Wi-Fi ကွန်ယက်ရရှိနိုင်သည်</item>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 0371543..324f0d7 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Medievolum"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Varslingsvolum"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standard ringetone"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Standard ringetone (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ringelyder"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Ukjent ringetone"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi-nettverk er tilgjengelig</item>
       <item quantity="one">Wi-Fi-nettverk er tilgjengelig</item>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index e039927..caf3688 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1065,10 +1065,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"मिडियाको मात्रा"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"सूचना भोल्युम"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"पूर्वनिर्धारित रिङटोन"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"पूर्वनिर्धारित रिङटोन (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"कुनै पनि होइन"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"रिङटोनहरू"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"अज्ञात रिङटोन"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi सञ्जालहरू उपलब्ध छन्</item>
       <item quantity="one">Wi-Fi सञ्जाल उपलब्ध छ</item>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 9c26340..0848304 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -204,9 +204,9 @@
     <string name="shutdown_confirm" product="tv" msgid="476672373995075359">"Je tv wordt uitgeschakeld.."</string>
     <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Je horloge wordt uitgeschakeld."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Je telefoon wordt uitgeschakeld."</string>
-    <string name="shutdown_confirm_question" msgid="2906544768881136183">"Wilt u afsluiten?"</string>
+    <string name="shutdown_confirm_question" msgid="2906544768881136183">"Wil je afsluiten?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Opnieuw opstarten in veilige modus"</string>
-    <string name="reboot_safemode_confirm" msgid="55293944502784668">"Wilt u opnieuw opstarten in de veilige modus? Als u dit doet, worden alle geïnstalleerde applicaties van derden uitgeschakeld. Ze worden weer ingeschakeld als u weer opnieuw opstart."</string>
+    <string name="reboot_safemode_confirm" msgid="55293944502784668">"Wil je opnieuw opstarten in de veilige modus? Als u dit doet, worden alle geïnstalleerde applicaties van derden uitgeschakeld. Ze worden weer ingeschakeld als u weer opnieuw opstart."</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recent"</string>
     <string name="no_recent_tasks" msgid="8794906658732193473">"Geen recente apps."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Tabletopties"</string>
@@ -356,9 +356,9 @@
     <string name="permdesc_writeCalendar" product="tv" msgid="1273290605500902507">"Hiermee kan de app afspraken toevoegen, verwijderen en wijzigen die u op je tv kunt aanpassen, inclusief afspraken van vrienden of collega\'s. Met deze toestemming zou de app berichten kunnen verzenden die afkomstig lijken te zijn van agenda-eigenaren of afspraken kunnen aanpassen zonder medeweten van de eigenaar."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Hiermee kan de app afspraken toevoegen, verwijderen en wijzigen die u kunt bewerken op je telefoon, inclusief afspraken van vrienden of collega\'s. Zo kan de app berichten verzenden die afkomstig lijken te zijn van agenda-eigenaren, of afspraken aanpassen zonder medeweten van de eigenaar."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"toegang tot extra opdrachten van locatieaanbieder"</string>
-    <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Hiermee kan de app toegang krijgen tot extra opdrachten voor de locatieprovider. De app kan hiermee de werking van GPS of andere locatiebronnen te verstoren."</string>
-    <string name="permlab_accessFineLocation" msgid="251034415460950944">"toegang tot precieze locatie (GPS- en netwerkgebaseerd)"</string>
-    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Hiermee kan de app je precieze locatie bepalen via GPS (Global Positioning System) of netwerklocatiebronnen zoals zendmasten en wifi. Deze locatieservices moeten zijn ingeschakeld en beschikbaar zijn op je apparaat voordat de app ze kan gebruiken. Apps kunnen dit gebruiken om te bepalen waar u bent en verbruiken mogelijk extra acculading."</string>
+    <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Hiermee kan de app toegang krijgen tot extra opdrachten voor de locatieprovider. De app kan hiermee de werking van gps of andere locatiebronnen te verstoren."</string>
+    <string name="permlab_accessFineLocation" msgid="251034415460950944">"toegang tot precieze locatie (gps- en netwerkgebaseerd)"</string>
+    <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Hiermee kan de app je precieze locatie bepalen via gps (Global Positioning System) of netwerklocatiebronnen zoals zendmasten en wifi. Deze locatieservices moeten zijn ingeschakeld en beschikbaar zijn op je apparaat voordat de app ze kan gebruiken. Apps kunnen dit gebruiken om te bepalen waar u bent en verbruiken mogelijk extra acculading."</string>
     <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"toegang tot geschatte locatie (netwerkgebaseerd)"</string>
     <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Hiermee kan de app beschikken over je geschatte locatie. Deze locatie wordt afgeleid van locatieservices die netwerklocatiebronnen zoals zendmasten en wifi gebruiken. Deze locatieservices moeten zijn ingeschakeld en beschikbaar zijn op je apparaat voordat de app ze kan gebruiken. Apps kunnen dit gebruiken om ongeveer te bepalen waar u zich bevindt."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"je audio-instellingen wijzigen"</string>
@@ -804,7 +804,7 @@
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Hiermee kan de app berichten toevoegen aan de inbox van je voicemail."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"geolocatiemachtigingen voor browser aanpassen"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Hiermee kan de app de geolocatiemachtigingen van de browser aanpassen. Schadelijke apps kunnen dit gebruiken om locatiegegevens te verzenden naar willekeurige websites."</string>
-    <string name="save_password_message" msgid="767344687139195790">"Wilt u dat de browser dit wachtwoord onthoudt?"</string>
+    <string name="save_password_message" msgid="767344687139195790">"Wil je dat de browser dit wachtwoord onthoudt?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Niet nu"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Onthouden"</string>
     <string name="save_password_never" msgid="8274330296785855105">"Nooit"</string>
@@ -1010,7 +1010,7 @@
     <string name="force_close" msgid="8346072094521265605">"OK"</string>
     <string name="report" msgid="4060218260984795706">"Melden"</string>
     <string name="wait" msgid="7147118217226317732">"Wachten"</string>
-    <string name="webpage_unresponsive" msgid="3272758351138122503">"De pagina reageert niet meer.\n\nWilt u de pagina sluiten?"</string>
+    <string name="webpage_unresponsive" msgid="3272758351138122503">"De pagina reageert niet meer.\n\nWil je de pagina sluiten?"</string>
     <string name="launch_warning_title" msgid="1547997780506713581">"App verplaatst"</string>
     <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> is nu actief."</string>
     <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> was het eerst gestart."</string>
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Mediavolume"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Meldingsvolume"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standaardbeltoon"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Standaardbeltoon (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Geen"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Beltonen"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Onbekende beltoon"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wifi-netwerken beschikbaar</item>
       <item quantity="one">Wifi-netwerk beschikbaar</item>
@@ -1111,7 +1117,7 @@
     <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"De verbinding met het wifi-netwerk wordt tijdelijk uitgeschakeld terwijl de telefoon verbonden is met <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="select_character" msgid="3365550120617701745">"Teken invoegen"</string>
     <string name="sms_control_title" msgid="7296612781128917719">"SMS-berichten verzenden"</string>
-    <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; verzendt moment een groot aantal sms-berichten. Wilt u toestaan ​​dat deze app berichten blijft verzenden?"</string>
+    <string name="sms_control_message" msgid="3867899169651496433">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; verzendt moment een groot aantal sms-berichten. Wil je toestaan ​​dat deze app berichten blijft verzenden?"</string>
     <string name="sms_control_yes" msgid="3663725993855816807">"Toestaan"</string>
     <string name="sms_control_no" msgid="625438561395534982">"Weigeren"</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; wil graag een bericht verzenden naar &lt;b&gt;<xliff:g id="DEST_ADDRESS">%2$s</xliff:g>&lt;/b&gt;."</string>
@@ -1220,7 +1226,7 @@
     <string name="dial_number_using" msgid="5789176425167573586">"Nummer bellen\nmet <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Contact maken\nmet <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"De volgende apps verzoeken om toegang tot je account, nu en in de toekomst."</string>
-    <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Wilt u dit verzoek toestaan?"</string>
+    <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Wil je dit verzoek toestaan?"</string>
     <string name="grant_permissions_header_text" msgid="6874497408201826708">"Verzoek om toegang"</string>
     <string name="allow" msgid="7225948811296386551">"Toestaan"</string>
     <string name="deny" msgid="2081879885755434506">"Weigeren"</string>
@@ -1277,7 +1283,7 @@
     <string name="gpsVerifYes" msgid="2346566072867213563">"Ja"</string>
     <string name="gpsVerifNo" msgid="1146564937346454865">"Nee"</string>
     <string name="sync_too_many_deletes" msgid="5296321850662746890">"Verwijderingslimiet overschreden"</string>
-    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Er zijn <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> verwijderde items voor <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g> , account <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> . Wat wilt u doen?"</string>
+    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"Er zijn <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> verwijderde items voor <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g> , account <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> . Wat wil je doen?"</string>
     <string name="sync_really_delete" msgid="2572600103122596243">"De items verwijderen."</string>
     <string name="sync_undo_deletes" msgid="2941317360600338602">"Verwijderingen ongedaan maken"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"Nu niets doen."</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index d3476aa..3e886bc 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"ਮੀਡੀਆ ਵੌਲਿਊਮ"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"ਸੂਚਨਾ ਵੌਲਿਊਮ"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਰਿੰਗਟੋਨ"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਰਿੰਗਟੋਨ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"ਕੋਈ ਨਹੀਂ"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"ਰਿੰਗਟੋਨਾਂ"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"ਅਗਿਆਤ ਰਿੰਗਟੋਨ"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Wi-Fi ਨੈੱਟਵਰਕਸ ਉਪਲਬਧ</item>
       <item quantity="other">Wi-Fi ਨੈੱਟਵਰਕਸ ਉਪਲਬਧ</item>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a7571ef..92a2e2a 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1105,10 +1105,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Głośność multimediów"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Głośność powiadomień"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Dzwonek domyślny"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Dzwonek domyślny (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Brak"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Dzwonki"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Nieznany dzwonek"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="few">Dostępne są sieci Wi-Fi</item>
       <item quantity="many">Dostępne są sieci Wi-Fi</item>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 24265ee..bf9e15d 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volume da mídia"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume da notificação"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Toque padrão"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Toque padrão (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Nenhum"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Toques"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Toque desconhecido"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Redes Wi-Fi disponíveis</item>
       <item quantity="other">Redes Wi-Fi disponíveis</item>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 6270210..e09daa5 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volume de multimédia"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume de notificações"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Toque predefinido"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Toque predefinido (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Nada"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Toques"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Toque desconhecido"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Redes Wi-Fi disponíveis</item>
       <item quantity="one">Rede Wi-Fi disponível</item>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 24265ee..bf9e15d 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volume da mídia"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume da notificação"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Toque padrão"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Toque padrão (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Nenhum"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Toques"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Toque desconhecido"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Redes Wi-Fi disponíveis</item>
       <item quantity="other">Redes Wi-Fi disponíveis</item>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 29c0a59..7f96d2e 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1082,10 +1082,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volumul media"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volum notificare"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Ton de apel prestabilit"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Ton de apel prestabilit (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Niciunul"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Tonuri de sonerie"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Ton de apel necunoscut"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="few">Rețele Wi-Fi disponibile</item>
       <item quantity="other">Rețele Wi-Fi disponibile</item>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ed6c798..9e25bb7 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1105,10 +1105,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Громкость мультимедиа"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Громкость уведомлений"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Мелодия по умолчанию"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"По умолчанию (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Без звука"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодии"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Неизвестная мелодия"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Есть доступные сети Wi-Fi</item>
       <item quantity="few">Есть доступные сети Wi-Fi</item>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 91d5bbe..b106464 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1061,10 +1061,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"මාධ්‍ය ශබ්දය"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"දැනුම්දීමේ ශබ්ද ත්‍රීවතාව"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"සුපුරුදු රින්ටෝනය සකසන්න"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"සුපුරුදු රින්ටෝනය (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"කිසිවක් නැත"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"රිගින්ටෝන"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"නොදන්නා රින්ටෝනය"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Wi-Fi ජාල තිබේ</item>
       <item quantity="other">Wi-Fi ජාල තිබේ</item>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 5c129af..50af3cc 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1105,10 +1105,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Hlasitosť médií"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Hlasitosť upozornení"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Predvolený tón zvonenia"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Predvolený tón (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Žiadny"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Tóny zvonenia"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Neznámy tón zvonenia"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="few">K dispozícii sú siete Wi-Fi</item>
       <item quantity="many">K dispozícii sú siete Wi-Fi</item>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 76f1e66..5bc756b 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1105,10 +1105,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Glasnost predstavnosti"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Glasnost obvestila"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Privzeta melodija zvonjenja"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Privzeta melodija zvonjenja (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Brez"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Melodije zvonjenja"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Neznana melodija zvonjenja"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Na voljo so omrežja Wi-Fi</item>
       <item quantity="two">Na voljo so omrežja Wi-Fi</item>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index 0fb3ebe..1095088 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"volumi i klipit \"media\""</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volumi i njoftimeve"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Zile e paracaktuar."</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Zilja e paracaktuar (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Asnjë"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Zilet"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Zile e panjohur"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Rrjete Wi-Fi ofrohen për përdorim</item>
       <item quantity="one">Një rrjet Wi-Fi ofrohet për përdorim</item>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index fdf8a6d..27d7cad 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1082,10 +1082,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Јачина звука медија"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Јачина звука обавештења"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Подразумевани звук звона"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Подразумевани звук звона (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Без звука"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Звукови звона"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Непознати звук звона"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Wi-Fi мреже су доступне</item>
       <item quantity="few">Wi-Fi мреже су доступне</item>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 340010f..b048762 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Mediavolym"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Meddelandevolym"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standardringsignal"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Standardringsignal (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Ingen"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ringsignaler"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Okänd ringsignal"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi-nätverk är tillgängliga</item>
       <item quantity="one">Wi-Fi-nätverk är tillgängligt</item>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 4832546..6cfd253 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1057,10 +1057,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Sauti ya midia"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Sauti ya arifa"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Mlio chaguo-msingi"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Mlio chaguo-msingi (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Hamna"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Toni za mlio"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Mlio amabo haujulikani"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Mitandao ya Wi-Fi inapatikana</item>
       <item quantity="one">Mtandao wa Wi-Fi unapatikana</item>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index f6bb25c..b391912 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"மீடியாவின் ஒலியளவு"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"அறிவிப்பின் ஒலியளவு"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"இயல்புநிலை ரிங்டோன்"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"இயல்புநிலை ரிங்டோன் (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"ஏதுமில்லை"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"ரிங்டோன்கள்"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"அறியப்படாத ரிங்டோன்"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">வைஃபை நெட்வொர்க்குகள் உள்ளன</item>
       <item quantity="one">வைஃபை நெட்வொர்க் உள்ளது</item>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 24bfebd..5ec586f 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"మీడియా వాల్యూమ్"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"నోటిఫికేషన్ వాల్యూమ్"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"డిఫాల్ట్ రింగ్‌టోన్"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"డిఫాల్ట్ రింగ్‌టోన్ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"ఏదీ వద్దు"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"రింగ్‌టోన్‌లు"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"తెలియని రింగ్‌టోన్"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi నెట్‌వర్క్‌లు అందుబాటులో ఉన్నాయి</item>
       <item quantity="one">Wi-Fi నెట్‌వర్క్ అందుబాటులో ఉంది</item>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 818bb9f..15cbd94 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"ระดับเสียงของสื่อ"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"ระดับเสียงของการแจ้งเตือน"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"เสียงเรียกเข้าเริ่มต้น"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"เสียงเรียกเข้าเริ่มต้น (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"ไม่มี"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"เสียงเรียกเข้า"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"ไม่ทราบเสียงเรียกเข้า"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">มีหลายเครือข่าย Wi-Fi ที่ใช้งานได้</item>
       <item quantity="one">มี 1 เครือข่าย Wi-Fi ที่ใช้งานได้</item>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 81c5fd0..31666ee 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Volume ng media"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Volume ng notification"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Default na ringtone"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Default na ringtone (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Wala"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Mga Ringtone"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Hindi kilalang ringtone"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Available ang mga Wi-Fi network</item>
       <item quantity="other">Available ang mga Wi-Fi network</item>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 12a5b7c..0126068 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Medya ses düzeyi"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Bildirim ses düzeyi"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Varsayılan zil sesi"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Varsayılan zil sesi (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Yok"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Zil sesleri"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Bilinmeyen zil sesi"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Kablosuz ağlar var</item>
       <item quantity="one">Kablosuz ağ var</item>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index fb0fda8..104badd 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1105,10 +1105,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Гучність медіа"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Гучність сповіщення"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Мелодія за умовчанням"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Мелодія за умовчанням (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Немає"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Мелодії"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Невідома мелодія"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Мережі Wi-Fi доступні</item>
       <item quantity="few">Мережі Wi-Fi доступні</item>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index d6eae64..f8224f2 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"میڈیا والیوم"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"اطلاع کا والیوم"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"ڈیفالٹ رنگ ٹون"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"ڈیفالٹ رنگ ٹون (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"کوئی نہیں"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"رنگ ٹونز"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"نامعلوم رنگ ٹون"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">‏Wi-Fi نیٹ ورکس دستیاب ہیں</item>
       <item quantity="one">‏Wi-Fi نیٹ ورک دستیاب ہے</item>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 5b7cf74..78b5400 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Multimedia ovozi"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Eslatma tovushi"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Standart rington"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Standart rington (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Yo‘q"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Ringtonlar"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Noma’lum rington"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Wi-Fi tarmoqlari aniqlandi</item>
       <item quantity="one">Wi-Fi tarmog‘i aniqlandi</item>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 42e0b0a..ca5e3bc 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Âm lượng phương tiện"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Âm lượng thông báo"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Nhạc chuông mặc định"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Nhạc chuông mặc định (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Không"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Nhạc chuông"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Nhạc chuông không xác định"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">Các mạng Wi-Fi khả dụng</item>
       <item quantity="one">Mạng Wi-Fi khả dụng</item>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 68e87c2..2126d12 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"媒体音量"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"默认铃声"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"默认铃声(<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"无"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"铃声"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"未知铃声"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">有可用的 WLAN 网络</item>
       <item quantity="one">有可用的 WLAN 网络</item>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 62bb44a..bdd9fe3 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"媒體音量"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"預設鈴聲"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"預設鈴聲 (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"無"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"鈴聲"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"不明鈴聲"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">有可用的 Wi-Fi 網絡</item>
       <item quantity="one">有可用的 Wi-Fi 網絡</item>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 0500c07..3c2146b 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"媒體音量"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"通知音量"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"預設鈴聲"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"預設鈴聲 (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"無"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"鈴聲"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"未知的鈴聲"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="other">有多個可用的 Wi-Fi 網路</item>
       <item quantity="one">有一個可用的 Wi-Fi 網路</item>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 849f292..011e4f7 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1059,10 +1059,16 @@
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Ivolumu yemidiya"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Ivolumu yesaziso"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"Iringithoni emisiwe"</string>
-    <string name="ringtone_default_with_actual" msgid="8129563480895990372">"Iringithoni ezenzakalelayo <xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>"</string>
+    <!-- no translation found for ringtone_default_with_actual (1767304850491060581) -->
+    <skip />
     <string name="ringtone_silent" msgid="7937634392408977062">"Akunalutho"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Amaringithoni"</string>
-    <string name="ringtone_unknown" msgid="5477919988701784788">"Iringithoni engaziwa"</string>
+    <!-- no translation found for ringtone_picker_title_alarm (6473325356070549702) -->
+    <skip />
+    <!-- no translation found for ringtone_picker_title_notification (4837740874822788802) -->
+    <skip />
+    <!-- no translation found for ringtone_unknown (3914515995813061520) -->
+    <skip />
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="one">Amanethiwekhi we-Wi-Fi ayatholakala</item>
       <item quantity="other">Amanethiwekhi we-Wi-Fi ayatholakala</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2d61e6e..acafbcf 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -582,7 +582,7 @@
         <!-- Image elements -->
         <!-- ============== -->
         <eat-comment />
-i
+
         <!-- Background that can be used behind parts of a UI that provide
              details on data the user is selecting.  For example, this is
              the background element of PreferenceActivity's embedded
@@ -1008,6 +1008,15 @@
         <!-- Background to use for toasts -->
         <attr name="toastFrameBackground" format="reference" />
 
+        <!-- Background to use for tooltip popups -->
+        <attr name="tooltipFrameBackground" format="reference" />
+
+        <!-- Foreground color to use for tooltip popups -->
+        <attr name="tooltipForegroundColor" format="reference|color" />
+
+        <!-- Background color to use for tooltip popups -->
+        <attr name="tooltipBackgroundColor" format="reference|color" />
+
         <!-- Theme to use for Search Dialogs -->
         <attr name="searchDialogTheme" format="reference" />
 
@@ -2865,6 +2874,9 @@
              {@link android.view.View#forceHasOverlappingRendering(boolean)}. -->
         <attr name="forceHasOverlappingRendering" format="boolean" />
 
+        <!-- Defines text displayed in a small popup window on hover or long press. -->
+        <attr name="tooltip" format="string" localization="suggested" />
+
     </declare-styleable>
 
     <!-- Attributes that can be assigned to a tag for a particular View. -->
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index de86cef..0995bc3 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -186,4 +186,7 @@
 
     <color name="resize_shadow_start_color">#2a000000</color>
     <color name="resize_shadow_end_color">#00000000</color>
+
+    <color name="tooltip_background_dark">#e6616161</color>
+    <color name="tooltip_background_light">#e6FFFFFF</color>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d4119d0..a7c5b2a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -128,6 +128,9 @@
     <integer name="config_activityShortDur">150</integer>
     <integer name="config_activityDefaultDur">220</integer>
 
+    <!-- The duration (in milliseconds) of the tooltip show/hide animations. -->
+    <integer name="config_tooltipAnimTime">150</integer>
+
     <!-- Duration for the dim animation behind a dialog.  This may be either
          a percentage, which is relative to the duration of the enter/open
          animation of the window being shown that is dimming behind, or it may
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 91d7227..5efa55c 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -487,4 +487,19 @@
 
     <!-- Minimum "smallest width" of the display for cascading menus to be enabled. -->
     <dimen name="cascading_menus_min_smallest_width">720dp</dimen>
+
+    <!-- Tooltip dimensions. -->
+    <!-- Vertical offset from the edge of the anchor view. -->
+    <dimen name="tooltip_y_offset">20dp</dimen>
+    <!-- Height of the tooltip. -->
+    <dimen name="tooltip_height">32dp</dimen>
+    <!-- The tooltip does not get closer than this to the window edge -->
+    <dimen name="tooltip_margin">8dp</dimen>
+    <!-- Left/right padding of the tooltip text. -->
+    <dimen name="tooltip_horizontal_padding">16dp</dimen>
+    <!-- Border corner radius of the tooltip window. -->
+    <dimen name="tooltip_corner_radius">2dp</dimen>
+    <!-- View with the height equal or above this threshold will have a tooltip anchored
+    to the mouse/touch position -->
+    <dimen name="tooltip_precise_anchor_threshold">96dp</dimen>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ed68582..ae82128 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2759,6 +2759,7 @@
         <public name="fontStyle" />
         <public name="font" />
         <public name="fontWeight" />
+        <public name="tooltip" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d42ec90..baf3cd8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4450,4 +4450,7 @@
 
     <!-- Label used by Telephony code, assigned as the display name for conference calls [CHAR LIMIT=60] -->
     <string name="conference_call">Conference Call</string>
+
+    <!-- Title for a tooltip popup window [CHAR LIMIT=NONE] -->
+    <string name="tooltip_popup_title">Tooltip Popup</string>
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 937428b..0f756b9 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -159,6 +159,11 @@
         <item name="windowExitAnimation">@anim/toast_exit</item>
     </style>
 
+    <style name="Animation.Tooltip">
+        <item name="windowEnterAnimation">@anim/tooltip_enter</item>
+        <item name="windowExitAnimation">@anim/tooltip_exit</item>
+    </style>
+
     <style name="Animation.DropDownDown">
         <item name="windowEnterAnimation">@anim/grow_fade_in</item>
         <item name="windowExitAnimation">@anim/shrink_fade_out</item>
@@ -950,6 +955,11 @@
         <item name="fontFamily">sans-serif-condensed</item>
     </style>
 
+    <style name="TextAppearance.Tooltip">
+        <item name="fontFamily">sans-serif</item>
+        <item name="textSize">14sp</item>
+    </style>
+
     <style name="Widget.ActivityChooserView">
         <item name="gravity">center</item>
         <item name="background">@drawable/ab_share_pack_holo_dark</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c719664..5b608b8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -435,6 +435,8 @@
   <java-symbol type="dimen" name="search_view_preferred_height" />
   <java-symbol type="dimen" name="textview_error_popup_default_width" />
   <java-symbol type="dimen" name="toast_y_offset" />
+  <java-symbol type="dimen" name="tooltip_precise_anchor_threshold" />
+  <java-symbol type="dimen" name="tooltip_y_offset" />
   <java-symbol type="dimen" name="action_bar_stacked_max_height" />
   <java-symbol type="dimen" name="action_bar_stacked_tab_max_width" />
   <java-symbol type="dimen" name="notification_text_size" />
@@ -1123,6 +1125,7 @@
   <java-symbol type="string" name="demo_starting_message" />
   <java-symbol type="string" name="demo_restarting_message" />
   <java-symbol type="string" name="conference_call" />
+  <java-symbol type="string" name="tooltip_popup_title" />
 
 
   <java-symbol type="plurals" name="bugreport_countdown" />
@@ -1373,6 +1376,7 @@
   <java-symbol type="layout" name="textview_hint" />
   <java-symbol type="layout" name="time_picker_legacy" />
   <java-symbol type="layout" name="time_picker_dialog" />
+  <java-symbol type="layout" name="tooltip" />
   <java-symbol type="layout" name="transient_notification" />
   <java-symbol type="layout" name="voice_interaction_session" />
   <java-symbol type="layout" name="web_text_view_dropdown" />
@@ -1423,6 +1427,7 @@
   <java-symbol type="style" name="Animation.DropDownUp" />
   <java-symbol type="style" name="Animation.DropDownDown" />
   <java-symbol type="style" name="Animation.PopupWindow" />
+  <java-symbol type="style" name="Animation.Tooltip" />
   <java-symbol type="style" name="Animation.TypingFilter" />
   <java-symbol type="style" name="Animation.TypingFilterRestore" />
   <java-symbol type="style" name="Animation.Dream" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 5b2522f..357eb4b 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -439,6 +439,11 @@
         <item name="lightRadius">@dimen/light_radius</item>
         <item name="ambientShadowAlpha">@dimen/ambient_shadow_alpha</item>
         <item name="spotShadowAlpha">@dimen/spot_shadow_alpha</item>
+
+        <!-- Tooltip popup properties -->
+        <item name="tooltipFrameBackground">@drawable/tooltip_frame</item>
+        <item name="tooltipForegroundColor">@color/bright_foreground_light</item>
+        <item name="tooltipBackgroundColor">@color/tooltip_background_light</item>
     </style>
 
     <!-- Variant of {@link #Theme} with no title bar -->
@@ -553,6 +558,10 @@
         <item name="floatingToolbarItemBackgroundDrawable">@drawable/item_background_material_light</item>
         <item name="floatingToolbarOpenDrawable">@drawable/ic_menu_moreoverflow_material_light</item>
         <item name="floatingToolbarPopupBackgroundDrawable">@drawable/floating_popup_background_light</item>
+
+        <!-- Tooltip popup colors -->
+        <item name="tooltipForegroundColor">@color/bright_foreground_dark</item>
+        <item name="tooltipBackgroundColor">@color/tooltip_background_dark</item>
     </style>
 
     <!-- Variant of {@link #Theme_Light} with no title bar -->
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 0de773b..92bb3ea 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -398,6 +398,10 @@
         <item name="colorControlHighlight">@color/ripple_material_dark</item>
         <item name="colorButtonNormal">@color/btn_default_material_dark</item>
         <item name="colorSwitchThumbNormal">@color/switch_thumb_material_dark</item>
+
+        <!-- Tooltip popup properties -->
+        <item name="tooltipForegroundColor">@color/foreground_material_light</item>
+        <item name="tooltipBackgroundColor">@color/tooltip_background_light</item>
     </style>
 
     <!-- Material theme (light version). -->
@@ -762,6 +766,10 @@
         <item name="colorControlHighlight">@color/ripple_material_light</item>
         <item name="colorButtonNormal">@color/btn_default_material_light</item>
         <item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
+
+        <!-- Tooltip popup properties -->
+        <item name="tooltipForegroundColor">@color/foreground_material_dark</item>
+        <item name="tooltipBackgroundColor">@color/tooltip_background_dark</item>
     </style>
 
     <!-- Variant of the material (light) theme that has a solid (opaque) action bar
diff --git a/core/tests/coretests/src/android/provider/SettingsProviderTest.java b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
index e6d3158..0a32e43 100644
--- a/core/tests/coretests/src/android/provider/SettingsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
@@ -349,6 +349,7 @@
         assertCanBeHandled(new Intent(Settings.ACTION_USER_DICTIONARY_SETTINGS));
         assertCanBeHandled(new Intent(Settings.ACTION_WIFI_IP_SETTINGS));
         assertCanBeHandled(new Intent(Settings.ACTION_WIFI_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_WIFI_SAVED_NETWORK_SETTINGS));
         assertCanBeHandled(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
     }
 
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 40a2833..00b5eda 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -15,14 +15,14 @@
 package android.graphics.drawable;
 
 import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorInflater;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
-import android.animation.Animator.AnimatorListener;
+import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
-import android.animation.ObjectAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityThread;
@@ -55,11 +55,8 @@
 import android.view.View;
 
 import com.android.internal.R;
-
 import com.android.internal.util.VirtualRefBasePtr;
 
-import dalvik.annotation.optimization.FastNative;
-
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -67,6 +64,8 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
+import dalvik.annotation.optimization.FastNative;
+
 /**
  * This class animates properties of a {@link android.graphics.drawable.VectorDrawable} with
  * animations defined using {@link android.animation.ObjectAnimator} or
@@ -91,9 +90,77 @@
  * <a name="VDExample"></a>
  * <li><h4>XML for the VectorDrawable containing properties to be animated</h4>
  * <p>
- * Animations can be performed on both group and path attributes, which requires groups and paths to
- * have unique names in the same VectorDrawable. Groups and paths without animations do not need to
- * be named.
+ * Animations can be performed on the animatable attributes in
+ * {@link android.graphics.drawable.VectorDrawable}. These attributes will be animated by
+ * {@link android.animation.ObjectAnimator}. The ObjectAnimator's target can be the root element,
+ * a group element or a path element. The targeted elements need to be named uniquely within
+ * the same VectorDrawable. Elements without animation do not need to be named.
+ * </p>
+ * <p>
+ * Here are all the animatable attributes in {@link android.graphics.drawable.VectorDrawable}:
+ * <table border="2" align="center" cellpadding="5">
+ *     <thead>
+ *         <tr>
+ *             <th>Element Name</th>
+ *             <th>Animatable attribute name</th>
+ *         </tr>
+ *     </thead>
+ *     <tr>
+ *         <td>&lt;vector&gt;</td>
+ *         <td>alpha</td>
+ *     </tr>
+ *     <tr>
+ *         <td rowspan="7">&lt;group&gt;</td>
+ *         <td>rotation</td>
+ *     </tr>
+ *     <tr>
+ *         <td>pivotX</td>
+ *     </tr>
+ *     <tr>
+ *         <td>pivotY</td>
+ *     </tr>
+ *     <tr>
+ *         <td>scaleX</td>
+ *     </tr>
+ *     <tr>
+ *         <td>scaleY</td>
+ *     </tr>
+ *     <tr>
+ *         <td>translateX</td>
+ *     </tr>
+ *     <tr>
+ *         <td>translateY</td>
+ *     </tr>
+ *     <tr>
+ *         <td rowspan="8">&lt;path&gt;</td>
+ *         <td>pathData</td>
+ *     </tr>
+ *     <tr>
+ *         <td>fillColor</td>
+ *     </tr>
+ *     <tr>
+ *         <td>strokeColor</td>
+ *     </tr>
+ *     <tr>
+ *         <td>strokeWidth</td>
+ *     </tr>
+ *     <tr>
+ *         <td>strokeAlpha</td>
+ *     </tr>
+ *     <tr>
+ *         <td>fillAlpha</td>
+ *     </tr>
+ *     <tr>
+ *         <td>trimPathStart</td>
+ *     </tr>
+ *     <tr>
+ *         <td>trimPathOffset</td>
+ *     </tr>
+ *     <tr>
+ *         <td>&lt;clip-path&gt;</td>
+ *         <td>pathData</td>
+ *     </tr>
+ * </table>
  * </p>
  * Below is an example of a VectorDrawable defined in vectordrawable.xml. This VectorDrawable is
  * referred to by its file name (not including file suffix) in the
@@ -121,9 +188,8 @@
  * <li><h4>XML for AnimatedVectorDrawable</h4>
  * <p>
  * An AnimatedVectorDrawable element has a VectorDrawable attribute, and one or more target
- * element(s). The target elements can be the path or group to be animated. Each target element
- * contains a name attribute that references a property (of a path or a group) to animate, and an
- * animation attribute that points to an ObjectAnimator or an AnimatorSet.
+ * element(s). The target element can specify its target by android:name attribute, and link the
+ * target with the proper ObjectAnimator or AnimatorSet by android:animation attribute.
  * </p>
  * The following code sample defines an AnimatedVectorDrawable. Note that the names refer to the
  * groups and paths in the <a href="#VDExample">VectorDrawable XML above</a>.
@@ -176,7 +242,8 @@
  * merge the XML files from the previous examples into one XML file:
  * </p>
  * <pre>
- * &lt;animated-vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot; &gt;
+ * &lt;animated-vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+ *                  xmlns:aapt=&quothttp://schemas.android.com/aapt&quot; &gt;
  *     &lt;aapt:attr name="android:drawable"&gt;
  *         &lt;vector
  *             android:height=&quot;64dp&quot;
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index e83104d..3a12419 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -77,36 +77,27 @@
  * <dl>
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of this vector drawable.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:width</code></dt>
  * <dd>Used to define the intrinsic width of the drawable.
  * This support all the dimension units, normally specified with dp.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:height</code></dt>
  * <dd>Used to define the intrinsic height the drawable.
  * This support all the dimension units, normally specified with dp.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:viewportWidth</code></dt>
  * <dd>Used to define the width of the viewport space. Viewport is basically
  * the virtual canvas where the paths are drawn on.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:viewportHeight</code></dt>
  * <dd>Used to define the height of the viewport space. Viewport is basically
  * the virtual canvas where the paths are drawn on.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:tint</code></dt>
  * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:tintMode</code></dt>
- * <dd>The Porter-Duff blending mode for the tint color. The default value is src_in.</dd>
- * <dd>Animatable : No.</dd>
+ * <dd>The Porter-Duff blending mode for the tint color. Default is src_in.</dd>
  * <dt><code>android:autoMirrored</code></dt>
  * <dd>Indicates if the drawable needs to be mirrored when its layout direction is
- * RTL (right-to-left).</dd>
- * <dd>Animatable : No.</dd>
+ * RTL (right-to-left). Default is false.</dd>
  * <dt><code>android:alpha</code></dt>
- * <dd>The opacity of this drawable.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The opacity of this drawable. Default is 1.0.</dd>
  * </dl></dd>
  * </dl>
  *
@@ -118,32 +109,24 @@
  * <dl>
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of the group.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:rotation</code></dt>
- * <dd>The degrees of rotation of the group.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The degrees of rotation of the group. Default is 0.</dd>
  * <dt><code>android:pivotX</code></dt>
  * <dd>The X coordinate of the pivot for the scale and rotation of the group.
- * This is defined in the viewport space.</dd>
- * <dd>Animatable : Yes.</dd>
+ * This is defined in the viewport space. Default is 0.</dd>
  * <dt><code>android:pivotY</code></dt>
  * <dd>The Y coordinate of the pivot for the scale and rotation of the group.
- * This is defined in the viewport space.</dd>
- * <dd>Animatable : Yes.</dd>
+ * This is defined in the viewport space. Default is 0.</dd>
  * <dt><code>android:scaleX</code></dt>
- * <dd>The amount of scale on the X Coordinate.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The amount of scale on the X Coordinate. Default is 1.</dd>
  * <dt><code>android:scaleY</code></dt>
- * <dd>The amount of scale on the Y coordinate.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The amount of scale on the Y coordinate. Default is 1.</dd>
  * <dt><code>android:translateX</code></dt>
  * <dd>The amount of translation on the X coordinate.
- * This is defined in the viewport space.</dd>
- * <dd>Animatable : Yes.</dd>
+ * This is defined in the viewport space. Default is 0.</dd>
  * <dt><code>android:translateY</code></dt>
  * <dd>The amount of translation on the Y coordinate.
- * This is defined in the viewport space.</dd>
- * <dd>Animatable : Yes.</dd>
+ * This is defined in the viewport space. Default is 0.</dd>
  * </dl></dd>
  * </dl>
  *
@@ -153,58 +136,44 @@
  * <dl>
  * <dt><code>android:name</code></dt>
  * <dd>Defines the name of the path.</dd>
- * <dd>Animatable : No.</dd>
  * <dt><code>android:pathData</code></dt>
  * <dd>Defines path data using exactly same format as "d" attribute
  * in the SVG's path data. This is defined in the viewport space.</dd>
- * <dd>Animatable : Yes.</dd>
  * <dt><code>android:fillColor</code></dt>
  * <dd>Specifies the color used to fill the path. May be a color or, for SDK 24+, a color state list
  * or a gradient color (See {@link android.R.styleable#GradientColor}
  * and {@link android.R.styleable#GradientColorItem}).
  * If this property is animated, any value set by the animation will override the original value.
  * No path fill is drawn if this property is not specified.</dd>
- * <dd>Animatable : Yes.</dd>
  * <dt><code>android:strokeColor</code></dt>
  * <dd>Specifies the color used to draw the path outline. May be a color or, for SDK 24+, a color
  * state list or a gradient color (See {@link android.R.styleable#GradientColor}
  * and {@link android.R.styleable#GradientColorItem}).
  * If this property is animated, any value set by the animation will override the original value.
  * No path outline is drawn if this property is not specified.</dd>
- * <dd>Animatable : Yes.</dd>
  * <dt><code>android:strokeWidth</code></dt>
- * <dd>The width a path stroke.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The width a path stroke. Default is 0.</dd>
  * <dt><code>android:strokeAlpha</code></dt>
- * <dd>The opacity of a path stroke.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The opacity of a path stroke. Default is 1.</dd>
  * <dt><code>android:fillAlpha</code></dt>
- * <dd>The opacity to fill the path with.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The opacity to fill the path with. Default is 1.</dd>
  * <dt><code>android:trimPathStart</code></dt>
- * <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The fraction of the path to trim from the start, in the range from 0 to 1. Default is 0.</dd>
  * <dt><code>android:trimPathEnd</code></dt>
- * <dd>The fraction of the path to trim from the end, in the range from 0 to 1.</dd>
- * <dd>Animatable : Yes.</dd>
+ * <dd>The fraction of the path to trim from the end, in the range from 0 to 1. Default is 1.</dd>
  * <dt><code>android:trimPathOffset</code></dt>
  * <dd>Shift trim region (allows showed region to include the start and end), in the range
- * from 0 to 1.</dd>
- * <dd>Animatable : Yes.</dd>
+ * from 0 to 1. Default is 0.</dd>
  * <dt><code>android:strokeLineCap</code></dt>
- * <dd>Sets the linecap for a stroked path: butt, round, square.</dd>
- * <dd>Animatable : No.</dd>
+ * <dd>Sets the linecap for a stroked path: butt, round, square. Default is butt.</dd>
  * <dt><code>android:strokeLineJoin</code></dt>
- * <dd>Sets the lineJoin for a stroked path: miter,round,bevel.</dd>
- * <dd>Animatable : No.</dd>
+ * <dd>Sets the lineJoin for a stroked path: miter,round,bevel. Default is miter.</dd>
  * <dt><code>android:strokeMiterLimit</code></dt>
- * <dd>Sets the Miter limit for a stroked path.</dd>
- * <dd>Animatable : No.</dd>
+ * <dd>Sets the Miter limit for a stroked path. Default is 4.</dd>
  * <dt><code>android:fillType</code></dt>
- * <dd>Sets the fillType for a path. The types can be either "evenOdd" or "nonZero". They behave the
- * same as SVG's "fill-rule" properties. For more details, see
+ * <dd>For SDK 24+, sets the fillType for a path. The types can be either "evenOdd" or "nonZero". They behave the
+ * same as SVG's "fill-rule" properties. Default is nonZero. For more details, see
  * <a href="https://www.w3.org/TR/SVG/painting.html#FillRuleProperty">FillRuleProperty</a></dd>
- * <dd>Animatable : No.</dd>
  * </dl></dd>
  *
  * </dl>
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index fdf4d52..eff2499 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -181,6 +181,7 @@
     external/skia/include/private \
     external/skia/src/core \
     external/skia/src/effects \
+    external/skia/src/image \
     external/harfbuzz_ng/src \
     external/freetype/include
 
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 2087fca..749efdd 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -116,6 +116,9 @@
         bool canDrawThisFrame = true;
     } out;
 
+    // This flag helps to disable projection for receiver nodes that do not have any backward
+    // projected children.
+    bool hasBackwardProjectedNodes = false;
     // TODO: Damage calculations
 };
 
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 7dcbbd0..da9002d 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -24,8 +24,41 @@
 namespace uirenderer {
 namespace skiapipeline {
 
+void RenderNodeDrawable::drawBackwardsProjectedNodes(SkCanvas* canvas, const SkiaDisplayList& displayList,
+        int nestLevel) {
+    LOG_ALWAYS_FATAL_IF(0 == nestLevel && !displayList.mProjectionReceiver);
+    for (auto& child : displayList.mChildNodes) {
+        const RenderProperties& childProperties = child.getNodeProperties();
+
+        //immediate children cannot be projected on their parent
+        if (childProperties.getProjectBackwards() && nestLevel > 0) {
+            SkAutoCanvasRestore acr2(canvas, true);
+            //Apply recorded matrix, which is a total matrix saved at recording time to avoid
+            //replaying all DL commands.
+            canvas->concat(child.getRecordedMatrix());
+            child.drawContent(canvas);
+        }
+
+        //skip walking sub-nodes if current display list contains a receiver with exception of
+        //level 0, which is a known receiver
+        if (0 == nestLevel || !displayList.containsProjectionReceiver()) {
+            SkAutoCanvasRestore acr(canvas, true);
+            SkMatrix nodeMatrix;
+            mat4 hwuiMatrix(child.getRecordedMatrix());
+            auto childNode = child.getRenderNode();
+            childNode->applyViewPropertyTransforms(hwuiMatrix);
+            hwuiMatrix.copyTo(nodeMatrix);
+            canvas->concat(nodeMatrix);
+            SkiaDisplayList* childDisplayList = static_cast<SkiaDisplayList*>(
+                (const_cast<DisplayList*>(childNode->getDisplayList())));
+            if (childDisplayList) {
+                drawBackwardsProjectedNodes(canvas, *childDisplayList, nestLevel+1);
+            }
+        }
+    }
+}
+
 static void clipOutline(const Outline& outline, SkCanvas* canvas, const SkRect* pendingClip) {
-    SkASSERT(outline.willClip());
     Rect possibleRect;
     float radius;
     LOG_ALWAYS_FATAL_IF(!outline.getAsRoundRect(&possibleRect, &radius),
@@ -74,53 +107,25 @@
     SkiaDisplayList* displayList = (SkiaDisplayList*)renderNode->getDisplayList();
 
     SkAutoCanvasRestore acr(canvas, true);
-
     const RenderProperties& properties = this->getNodeProperties();
-    if (displayList->mIsProjectionReceiver) {
-        // this node is a projection receiver. We will gather the projected nodes as we draw our
-        // children, and then draw them on top of this node's content.
-        std::vector<ProjectedChild> newList;
-        for (auto& child : displayList->mChildNodes) {
-            // our direct children are not supposed to project into us (nodes project to, at the
-            // nearest, their grandparents). So we "delay" the list's activation one level by
-            // passing it into mNextProjectedChildrenTarget rather than mProjectedChildrenTarget.
-            child.mProjectedChildrenTarget = mNextProjectedChildrenTarget;
-            child.mNextProjectedChildrenTarget = &newList;
+    //pass this outline to the children that may clip backward projected nodes
+    displayList->mProjectedOutline = displayList->containsProjectionReceiver()
+            ? &properties.getOutline() : nullptr;
+    if (!properties.getProjectBackwards()) {
+        drawContent(canvas);
+        if (mProjectedDisplayList) {
+            acr.restore(); //draw projected children using parent matrix
+            LOG_ALWAYS_FATAL_IF(!mProjectedDisplayList->mProjectedOutline);
+            const bool shouldClip = mProjectedDisplayList->mProjectedOutline->getPath();
+            SkAutoCanvasRestore acr2(canvas, shouldClip);
+            canvas->setMatrix(mProjectedDisplayList->mProjectedReceiverParentMatrix);
+            if (shouldClip) {
+                clipOutline(*mProjectedDisplayList->mProjectedOutline, canvas, nullptr);
+            }
+            drawBackwardsProjectedNodes(canvas, *mProjectedDisplayList);
         }
-        // draw ourselves and our children. As a side effect, this will add projected nodes to
-        // newList.
-        this->drawContent(canvas);
-        bool willClip = properties.getOutline().willClip();
-        if (willClip) {
-            canvas->save();
-            clipOutline(properties.getOutline(), canvas, nullptr);
-        }
-        // draw the collected projected nodes
-        for (auto& projectedChild : newList) {
-            canvas->setMatrix(projectedChild.matrix);
-            projectedChild.node->drawContent(canvas);
-        }
-        if (willClip) {
-            canvas->restore();
-        }
-    } else {
-        if (properties.getProjectBackwards() && mProjectedChildrenTarget) {
-            // We are supposed to project this node, so add it to the list and do not actually draw
-            // yet. It will be drawn by its projection receiver.
-            mProjectedChildrenTarget->push_back({ this, canvas->getTotalMatrix() });
-            return;
-        }
-        for (auto& child : displayList->mChildNodes) {
-            // storing these values in the nodes themselves is a bit ugly; they should "really" be
-            // function parameters, but we have to go through the preexisting draw() method and
-            // therefore cannot add additional parameters to it
-            child.mProjectedChildrenTarget = mNextProjectedChildrenTarget;
-            child.mNextProjectedChildrenTarget = mNextProjectedChildrenTarget;
-        }
-        this->drawContent(canvas);
     }
-    mProjectedChildrenTarget = nullptr;
-    mNextProjectedChildrenTarget = nullptr;
+    displayList->mProjectedOutline = nullptr;
 }
 
 static bool layerNeedsPaint(const LayerProperties& properties,
@@ -148,6 +153,10 @@
     if (mComposeLayer) {
         setViewProperties(properties, canvas, &alphaMultiplier);
     }
+    SkiaDisplayList* displayList = (SkiaDisplayList*)mRenderNode->getDisplayList();
+    if (displayList->containsProjectionReceiver()) {
+        displayList->mProjectedReceiverParentMatrix = canvas->getTotalMatrix();
+    }
 
     //TODO should we let the bound of the drawable do this for us?
     const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.h b/libs/hwui/pipeline/skia/RenderNodeDrawable.h
index a2ffc6c..3eed647 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.h
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.h
@@ -29,6 +29,8 @@
 
 namespace skiapipeline {
 
+class SkiaDisplayList;
+
 /**
  * This drawable wraps a RenderNode and enables it to be recorded into a list
  * of Skia drawing commands.
@@ -36,18 +38,6 @@
 class RenderNodeDrawable : public SkDrawable {
 public:
     /**
-     * This struct contains a pointer to a node that is to be
-     * projected into the drawing order of its closest ancestor
-     * (excluding its parent) that is marked as a projection
-     * receiver. The matrix is used to ensure that the node is
-     * drawn with same matrix as it would have prior to projection.
-     */
-    struct ProjectedChild {
-        const RenderNodeDrawable* node;
-        const SkMatrix matrix;
-    };
-
-    /**
      * Creates a new RenderNodeDrawable backed by a render node.
      *
      * @param node that has to be drawn
@@ -86,6 +76,14 @@
      */
     const SkMatrix& getRecordedMatrix() const { return mRecordedTransform; }
 
+    /**
+     * Sets a pointer to a display list of the parent render node. The display list is used when
+     * drawing backward projected nodes, when this node is a projection receiver.
+     */
+    void setProjectedDisplayList(SkiaDisplayList* projectedDisplayList) {
+        mProjectedDisplayList = projectedDisplayList;
+    }
+
 protected:
     /*
      * Return the (conservative) bounds of what the drawable will draw.
@@ -108,6 +106,16 @@
     sp<RenderNode> mRenderNode;
 
     /**
+     * Walks recursively the display list and draws the content of backward projected nodes.
+     *
+     * @param canvas used to draw the backward projected nodes
+     * @param displayList is a display list that contains a projection receiver
+     * @param nestLevel should be always 0. Used to track how far we are from the receiver.
+     */
+    void drawBackwardsProjectedNodes(SkCanvas* canvas, const SkiaDisplayList& displayList,
+            int nestLevel = 0);
+
+    /**
      * Applies the rendering properties of a view onto a SkCanvas.
      */
     static void setViewProperties(const RenderProperties& properties, SkCanvas* canvas,
@@ -126,19 +134,6 @@
      */
     const bool mComposeLayer;
 
-    /**
-     * List to which we will add any projected children we encounter while walking our descendents.
-     * This pointer is valid only while the node (including its children) is actively being drawn.
-     */
-    std::vector<ProjectedChild>* mProjectedChildrenTarget = nullptr;
-
-    /**
-     * The value to which we should set our children's mProjectedChildrenTarget. We use two pointers
-     * (mProjectedChildrenTarget and mNextProjectedChildrenTarget) because we need to skip over our
-     * parent when looking for a projection receiver.
-     */
-    std::vector<ProjectedChild>* mNextProjectedChildrenTarget = nullptr;
-
     /*
      * True if the render node is in a reordering section
      */
@@ -148,6 +143,11 @@
      *  Draw the content into a canvas, depending on the render node layer type and mComposeLayer.
      */
     void drawContent(SkCanvas* canvas) const;
+
+    /*
+     * display list that is searched for any render nodes with getProjectBackwards==true
+     */
+    SkiaDisplayList* mProjectedDisplayList = nullptr;
 };
 
 }; // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index 2ad7f74..9db8cd3 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -64,16 +64,31 @@
         info.canvasContext.unpinImages();
     }
 
+    bool hasBackwardProjectedNodesHere = false;
+    bool hasBackwardProjectedNodesSubtree= false;
+
     for (auto& child : mChildNodes) {
+        hasBackwardProjectedNodesHere |= child.getNodeProperties().getProjectBackwards();
         RenderNode* childNode = child.getRenderNode();
         Matrix4 mat4(child.getRecordedMatrix());
         info.damageAccumulator->pushTransform(&mat4);
         // TODO: a layer is needed if the canvas is rotated or has a non-rect clip
-        bool childFunctorsNeedLayer = functorsNeedLayer;
-        childFn(childNode, info, childFunctorsNeedLayer);
+        info.hasBackwardProjectedNodes = false;
+        childFn(childNode, info, functorsNeedLayer);
+        hasBackwardProjectedNodesSubtree |= info.hasBackwardProjectedNodes;
         info.damageAccumulator->popTransform();
     }
 
+    //The purpose of next block of code is to reset projected display list if there are no
+    //backward projected nodes. This speeds up drawing, by avoiding an extra walk of the tree
+    if (mProjectionReceiver) {
+        mProjectionReceiver->setProjectedDisplayList(hasBackwardProjectedNodesSubtree ? this : nullptr);
+        info.hasBackwardProjectedNodes = hasBackwardProjectedNodesHere;
+    } else {
+        info.hasBackwardProjectedNodes = hasBackwardProjectedNodesSubtree
+                || hasBackwardProjectedNodesHere;
+    }
+
     bool isDirty = false;
     for (auto& vectorDrawable : mVectorDrawables) {
         // If any vector drawable in the display list needs update, damage the node.
@@ -86,7 +101,7 @@
 }
 
 void SkiaDisplayList::reset(SkRect bounds) {
-    mIsProjectionReceiver = false;
+    mProjectionReceiver = nullptr;
 
     mDrawable->reset(bounds);
 
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index f34b485..ff86fd1 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -26,6 +26,9 @@
 
 namespace android {
 namespace uirenderer {
+
+class Outline;
+
 namespace skiapipeline {
 
 /**
@@ -119,6 +122,11 @@
     void updateChildren(std::function<void(RenderNode*)> updateFn) override;
 
     /**
+     *  Returns true if there is a child render node that is a projection receiver.
+     */
+    inline bool containsProjectionReceiver() const { return mProjectionReceiver; }
+
+    /**
      * We use std::deque here because (1) we need to iterate through these
      * elements and (2) mDrawable holds pointers to the elements, so they cannot
      * relocate.
@@ -129,7 +137,22 @@
     std::vector<VectorDrawableRoot*> mVectorDrawables;
     sk_sp<SkLiteDL> mDrawable;
 
-    bool mIsProjectionReceiver = false;
+    //mProjectionReceiver points to a child node (stored in mChildNodes) that is as a projection
+    //receiver. It is set at record time and used at both prepare and draw tree traversals to
+    //make sure backward projected nodes are found and drawn immediately after mProjectionReceiver.
+    RenderNodeDrawable* mProjectionReceiver = nullptr;
+
+    //mProjectedOutline is valid only when render node tree is traversed during the draw pass.
+    //Render nodes that have a child receiver node, will store a pointer to their outline in
+    //mProjectedOutline. Child receiver node will apply the clip before any backward projected
+    //node is drawn.
+    const Outline* mProjectedOutline = nullptr;
+
+    //mProjectedReceiverParentMatrix is valid when render node tree is traversed during the draw
+    //pass. Render nodes that have a child receiver node, will store their matrix in
+    //mProjectedReceiverParentMatrix. Child receiver node will set the matrix and then clip with the
+    //outline of their parent.
+    SkMatrix mProjectedReceiverParentMatrix;
 };
 
 }; // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 621816a..6df544f 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -108,11 +108,12 @@
 
     // record the child node
     mDisplayList->mChildNodes.emplace_back(renderNode, asSkCanvas(), true, mCurrentBarrier);
-    drawDrawable(&mDisplayList->mChildNodes.back());
+    auto& renderNodeDrawable = mDisplayList->mChildNodes.back();
+    drawDrawable(&renderNodeDrawable);
 
     // use staging property, since recording on UI thread
     if (renderNode->stagingProperties().isProjectionReceiver()) {
-        mDisplayList->mIsProjectionReceiver = true;
+        mDisplayList->mProjectionReceiver = &renderNodeDrawable;
         // set projectionReceiveIndex so that RenderNode.hasProjectionReceiver returns true
         mDisplayList->projectionReceiveIndex = mDisplayList->mChildNodes.size() - 1;
     }
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 01046e1..8c956e5 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -1487,6 +1487,8 @@
     *layerHandle = nullptr;
 }
 
+namespace {
+
 static void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) {
     SkPaint paint;
     // order put in blue channel, transparent so overlapped content doesn't get rejected
@@ -1502,15 +1504,30 @@
     node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z);
     canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
 }
-RENDERTHREAD_TEST(FrameBuilder, zReorder) {
-    class ZReorderTestRenderer : public TestRendererBase {
-    public:
-        void onRectOp(const RectOp& op, const BakedOpState& state) override {
-            int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel
-            EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order";
-        }
-    };
 
+static void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder,
+        std::function<void(RenderProperties& props, RecordingCanvas& canvas)> setup) {
+    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [expectedDrawOrder, setup](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedRect(&canvas, expectedDrawOrder);
+        if (setup) {
+             setup(props, canvas);
+        }
+    });
+    canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
+}
+
+class ZReorderTestRenderer : public TestRendererBase {
+public:
+    void onRectOp(const RectOp& op, const BakedOpState& state) override {
+        int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel
+        EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order";
+    }
+};
+
+} // end anonymous namespace
+
+RENDERTHREAD_TEST(FrameBuilder, zReorder) {
     auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
             [](RenderProperties& props, RecordingCanvas& canvas) {
         drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder
@@ -2238,5 +2255,349 @@
     EXPECT_EQ(1, renderer.getIndex());
 }
 
+TEST(FrameBuilder, projectionReorderProjectedInMiddle) {
+    /* R is backward projected on B
+                A
+               / \
+              B   C
+                  |
+                  R
+    */
+    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
+            props.setProjectionReceiver(true);
+        } ); //nodeB
+        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
+            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
+
+    ZReorderTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(3, renderer.getIndex());
+}
+
+TEST(FrameBuilder, projectionReorderProjectLast) {
+    /* R is backward projected on E
+                  A
+                / | \
+               /  |  \
+              B   C   E
+                  |
+                  R
+    */
+    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0,  nullptr); //nodeB
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+            drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 2
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 3
+            props.setProjectionReceiver(true);
+        } ); //nodeE
+    }); //nodeA
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
+
+    ZReorderTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(4, renderer.getIndex());
+}
+
+TEST(FrameBuilder, projectionReorderNoReceivable) {
+    /* R is backward projected without receiver
+                A
+               / \
+              B   C
+                  |
+                  R
+    */
+     auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, nullptr); //nodeB
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+            drawOrderedNode(&canvas, 255,  [](RenderProperties& props, RecordingCanvas& canvas) {
+                //not having a projection receiver is an undefined behavior
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
+
+    ZReorderTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(2, renderer.getIndex());
+}
+
+TEST(FrameBuilder, projectionReorderParentReceivable) {
+    /* R is backward projected on C
+                A
+               / \
+              B   C
+                  |
+                  R
+    */
+     auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, nullptr); //nodeB
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+            props.setProjectionReceiver(true);
+            drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
+
+    ZReorderTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(3, renderer.getIndex());
+}
+
+TEST(FrameBuilder, projectionReorderSameNodeReceivable) {
+     auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, nullptr); //nodeB
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+            drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) {
+                //having a node that is projected on itself is an undefined/unexpected behavior
+                props.setProjectionReceiver(true);
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
+
+    ZReorderTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(2, renderer.getIndex());
+}
+
+TEST(FrameBuilder, projectionReorderProjectedSibling) {
+    //TODO: this test together with the next "projectionReorderProjectedSibling2" likely expose a
+    //bug in HWUI. First test draws R, while the second test does not draw R for a nearly identical
+    //tree setup. The correct behaviour is to not draw R, because the receiver cannot be a sibling
+    /* R is backward projected on B. R is not expected to be drawn (see Sibling2 outcome below),
+       but for some reason it is drawn.
+                A
+               /|\
+              / | \
+             B  C  R
+    */
+    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
+            props.setProjectionReceiver(true);
+        } ); //nodeB
+        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
+        } ); //nodeC
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+            props.setProjectBackwards(true);
+            props.setClipToBounds(false);
+        } ); //nodeR
+    }); //nodeA
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
+
+    ZReorderTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(3, renderer.getIndex());
+}
+
+TEST(FrameBuilder, projectionReorderProjectedSibling2) {
+    /* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed.
+                A
+                |
+                G
+               /|\
+              / | \
+             B  C  R
+    */
+    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //G
+            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //B
+                props.setProjectionReceiver(true);
+            } ); //nodeB
+            drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
+            } ); //nodeC
+            drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) { //R
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeG
+    }); //nodeA
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
+
+    ZReorderTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(3, renderer.getIndex());
+}
+
+TEST(FrameBuilder, projectionReorderGrandparentReceivable) {
+    /* R is backward projected on B
+                A
+                |
+                B
+                |
+                C
+                |
+                R
+    */
+    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
+            props.setProjectionReceiver(true);
+            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
+                drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
+                    props.setProjectBackwards(true);
+                    props.setClipToBounds(false);
+                } ); //nodeR
+            } ); //nodeC
+        } ); //nodeB
+    }); //nodeA
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
+
+    ZReorderTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(3, renderer.getIndex());
+}
+
+TEST(FrameBuilder, projectionReorderTwoReceivables) {
+    /* B and G are receivables, R is backward projected
+                A
+               / \
+              B   C
+                 / \
+                G   R
+    */
+    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
+            props.setProjectionReceiver(true);
+        } ); //nodeB
+        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
+            drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //G
+                props.setProjectionReceiver(true);
+            } ); //nodeG
+            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //R
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
+
+    ZReorderTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(4, renderer.getIndex());
+}
+
+TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario) {
+    /* B and G are receivables, G is backward projected
+                A
+               / \
+              B   C
+                 / \
+                G   R
+    */
+    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
+            props.setProjectionReceiver(true);
+        } ); //nodeB
+        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
+            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //G
+                props.setProjectionReceiver(true);
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeG
+            drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
+
+    ZReorderTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(4, renderer.getIndex());
+}
+
+TEST(FrameBuilder, projectionReorderTwoReceivablesDeeper) {
+    /* B and G are receivables, R is backward projected
+                A
+               / \
+              B   C
+                 / \
+                G   D
+                    |
+                    R
+    */
+    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
+            props.setProjectionReceiver(true);
+        } ); //nodeB
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //C
+            drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //G
+                props.setProjectionReceiver(true);
+            } ); //nodeG
+            drawOrderedNode(&canvas, 4, [](RenderProperties& props, RecordingCanvas& canvas) { //D
+                drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R
+                    props.setProjectBackwards(true);
+                    props.setClipToBounds(false);
+                } ); //nodeR
+            } ); //nodeD
+        } ); //nodeC
+    }); //nodeA
+
+    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
+            sLightGeometry, Caches::getInstance());
+    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
+
+    ZReorderTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(5, renderer.getIndex());
+}
+
 } // namespace uirenderer
 } // namespace android
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 623d971..ae4f0f4 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -21,11 +21,14 @@
 #include "DamageAccumulator.h"
 #include "IContextFactory.h"
 #include "pipeline/skia/SkiaDisplayList.h"
+#include "pipeline/skia/SkiaPipeline.h"
 #include "pipeline/skia/SkiaRecordingCanvas.h"
 #include "renderthread/CanvasContext.h"
 #include "tests/common/TestUtils.h"
 #include "SkiaCanvas.h"
+#include <SkSurface_Base.h>
 #include <SkLiteRecorder.h>
+#include <SkClipStack.h>
 #include <string.h>
 
 
@@ -51,6 +54,8 @@
     ASSERT_EQ(drawable.getRecordedMatrix(), canvas.getTotalMatrix());
 }
 
+namespace {
+
 static void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) {
     SkPaint paint;
     // order put in blue channel, transparent so overlapped content doesn't get rejected
@@ -67,18 +72,33 @@
     canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
 }
 
-TEST(RenderNodeDrawable, zReorder) {
-    class ZReorderCanvas : public SkCanvas {
-    public:
-        ZReorderCanvas(int width, int height) : SkCanvas(width, height) {}
-        void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
-            int expectedOrder = SkColorGetB(paint.getColor()); // extract order from blue channel
-            EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order";
+static void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder,
+        std::function<void(RenderProperties& props, SkiaRecordingCanvas& canvas)> setup) {
+    auto node = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [expectedDrawOrder, setup](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedRect(&canvas, expectedDrawOrder);
+        if (setup) {
+             setup(props, canvas);
         }
-        int getIndex() { return mIndex; }
-    protected:
-        int mIndex = 0;
-    };
+    });
+    canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
+}
+
+class ZReorderCanvas : public SkCanvas {
+public:
+    ZReorderCanvas(int width, int height) : SkCanvas(width, height) {}
+    void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
+        int expectedOrder = SkColorGetB(paint.getColor()); // extract order from blue channel
+        EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order";
+    }
+    int getIndex() { return mIndex; }
+protected:
+    int mIndex = 0;
+};
+
+} // end anonymous namespace
+
+TEST(RenderNodeDrawable, zReorder) {
 
     auto parent = TestUtils::createSkiaNode(0, 0, 100, 100,
             [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
@@ -136,42 +156,622 @@
     rootNode->setLayerSurface(sk_sp<SkSurface>());
 }
 
-//TODO: refactor to cover test cases from FrameBuilderTests_projectionReorder
-//validate with bounds and projection path mask.
-//TODO: research if we could hook in and mock/validate different aspects of the drawing,
-//instead of validating pixels
-TEST(RenderNodeDrawable, projectDraw) {
-    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
-    SkCanvas& canvas = *surface->getCanvas();
-    canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
-    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+namespace {
+class ContextFactory : public IContextFactory {
+public:
+    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override {
+        return new AnimationContext(clock);
+    }
+};
 
-    auto redNode = TestUtils::createSkiaNode(0, 0, 1, 1,
-        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
-            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
-        }, "redNode");
+inline SkRect getBounds(const SkCanvas* canvas) {
+    SkClipStack::BoundsType boundType;
+    SkRect clipBounds;
+    canvas->getClipStack()->getBounds(&clipBounds, &boundType);
+    return clipBounds;
+}
+inline SkRect getLocalBounds(const SkCanvas* canvas) {
+    SkMatrix invertedTotalMatrix;
+    EXPECT_TRUE(canvas->getTotalMatrix().invert(&invertedTotalMatrix));
+    SkRect outlineInDeviceCoord = getBounds(canvas);
+    SkRect outlineInLocalCoord;
+    invertedTotalMatrix.mapRect(&outlineInLocalCoord, outlineInDeviceCoord);
+    return outlineInLocalCoord;
+}
+} // end anonymous namespace
 
-    auto greenNodeWithRedChild = TestUtils::createSkiaNode(0, 0, 1, 1,
-        [&](RenderProperties& props, SkiaRecordingCanvas& greenCanvasWithRedChild) {
-            greenCanvasWithRedChild.drawRenderNode(redNode.get());
-            greenCanvasWithRedChild.drawColor(SK_ColorGREEN, SkBlendMode::kSrcOver);
-        }, "greenNodeWithRedChild");
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorder) {
+    static const int SCROLL_X = 5;
+    static const int SCROLL_Y = 10;
+    class ProjectionTestCanvas : public SkCanvas {
+    public:
+        ProjectionTestCanvas(int width, int height) : SkCanvas(width, height) {}
+        void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
+            const int index = mIndex++;
+            SkMatrix expectedMatrix;;
+            switch (index) {
+            case 0:  //this is node "B"
+                EXPECT_EQ(SkRect::MakeWH(100, 100), rect);
+                EXPECT_EQ(SK_ColorWHITE, paint.getColor());
+                expectedMatrix.reset();
+                EXPECT_EQ(SkRect::MakeLTRB(0, 0, 100, 100), getBounds(this));
+                break;
+            case 1:  //this is node "P"
+                EXPECT_EQ(SkRect::MakeLTRB(-10, -10, 60, 60), rect);
+                EXPECT_EQ(SK_ColorDKGRAY, paint.getColor());
+                expectedMatrix.setTranslate(50 - SCROLL_X, 50 - SCROLL_Y);
+                EXPECT_EQ(SkRect::MakeLTRB(-35, -30, 45, 50), getLocalBounds(this));
+                break;
+            case 2:  //this is node "C"
+                EXPECT_EQ(SkRect::MakeWH(100, 50), rect);
+                EXPECT_EQ(SK_ColorBLUE, paint.getColor());
+                expectedMatrix.setTranslate(-SCROLL_X, 50 - SCROLL_Y);
+                EXPECT_EQ(SkRect::MakeLTRB(0, 40, 95, 90), getBounds(this));
+                break;
+            default:
+                ADD_FAILURE();
+            }
+            EXPECT_EQ(expectedMatrix, getTotalMatrix());
+        }
 
-    auto rootNode = TestUtils::createSkiaNode(0, 0, 1, 1,
-        [&](RenderProperties& props, SkiaRecordingCanvas& rootCanvas) {
-            rootCanvas.drawRenderNode(greenNodeWithRedChild.get());
-        }, "rootNode");
-    SkiaDisplayList* rootDisplayList = static_cast<SkiaDisplayList*>(
-        (const_cast<DisplayList*>(rootNode->getDisplayList())));
+        int getIndex() { return mIndex; }
+    protected:
+        int mIndex = 0;
+    };
 
-    RenderNodeDrawable rootDrawable(rootNode.get(), &canvas, false);
-    canvas.drawDrawable(&rootDrawable);
-    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorGREEN);
+    /**
+     * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C)
+     * with a projecting child (P) of its own. P would normally draw between B and C's "background"
+     * draw, but because it is projected backwards, it's drawn in between B and C.
+     *
+     * The parent is scrolled by SCROLL_X/SCROLL_Y, but this does not affect the background
+     * (which isn't affected by scroll).
+     */
+    auto receiverBackground = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+        properties.setProjectionReceiver(true);
+        // scroll doesn't apply to background, so undone via translationX/Y
+        // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
+        properties.setTranslationX(SCROLL_X);
+        properties.setTranslationY(SCROLL_Y);
 
-    //project redNode on rootNode, which will change the test outcome,
-    //because redNode will draw after greenNodeWithRedChild
-    rootDisplayList->mIsProjectionReceiver = true;
-    redNode->animatorProperties().setProjectBackwards(true);
-    canvas.drawDrawable(&rootDrawable);
-    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
+        SkPaint paint;
+        paint.setColor(SK_ColorWHITE);
+        canvas.drawRect(0, 0, 100, 100, paint);
+    }, "B");
+
+    auto projectingRipple = TestUtils::createSkiaNode(50, 0, 100, 50,
+            [](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+        properties.setProjectBackwards(true);
+        properties.setClipToBounds(false);
+        SkPaint paint;
+        paint.setColor(SK_ColorDKGRAY);
+        canvas.drawRect(-10, -10, 60, 60, paint);
+    }, "P");
+    auto child = TestUtils::createSkiaNode(0, 50, 100, 100,
+            [&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+        SkPaint paint;
+        paint.setColor(SK_ColorBLUE);
+        canvas.drawRect(0, 0, 100, 50, paint);
+        canvas.drawRenderNode(projectingRipple.get());
+    }, "C");
+    auto parent = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [&receiverBackground, &child](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+        // Set a rect outline for the projecting ripple to be masked against.
+        properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f);
+
+        canvas.save(SaveFlags::MatrixClip);
+        canvas.translate(-SCROLL_X, -SCROLL_Y); // Apply scroll (note: bg undoes this internally)
+        canvas.drawRenderNode(receiverBackground.get());
+        canvas.drawRenderNode(child.get());
+        canvas.restore();
+    }, "A");
+    ContextFactory contextFactory;
+    std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
+            renderThread, false, parent.get(), &contextFactory));
+    TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
+    DamageAccumulator damageAccumulator;
+    info.damageAccumulator = &damageAccumulator;
+    info.observer = nullptr;
+    parent->prepareTree(info);
+
+    //parent(A)             -> (receiverBackground, child)
+    //child(C)              -> (rect[0, 0, 100, 50], projectingRipple)
+    //projectingRipple(P)   -> (rect[-10, -10, 60, 60]) -> projects backwards
+    //receiverBackground(B) -> (rect[0, 0, 100, 100]) -> projection receiver
+
+    //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
+    ProjectionTestCanvas canvas(100, 100);
+    RenderNodeDrawable drawable(parent.get(), &canvas, true);
+    canvas.drawDrawable(&drawable);
+    EXPECT_EQ(3, canvas.getIndex());
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionHwLayer) {
+    /* R is backward projected on B and C is a layer.
+                A
+               / \
+              B   C
+                  |
+                  R
+    */
+    static const int SCROLL_X = 5;
+    static const int SCROLL_Y = 10;
+    static const int CANVAS_WIDTH = 400;
+    static const int CANVAS_HEIGHT = 400;
+    static const int LAYER_WIDTH = 200;
+    static const int LAYER_HEIGHT = 200;
+    class ProjectionTestCanvas : public SkCanvas {
+    public:
+        ProjectionTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
+        void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
+                const SkPaint&) override {
+            EXPECT_EQ(0, mIndex++); //part of painting the layer
+            EXPECT_EQ(SkRect::MakeLTRB(0, 0, LAYER_WIDTH, LAYER_HEIGHT), getBounds(this));
+        }
+        void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
+            EXPECT_EQ(1, mIndex++);
+            EXPECT_EQ(SkRect::MakeLTRB(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), getBounds(this));
+        }
+        void onDrawOval(const SkRect&, const SkPaint&) override {
+            EXPECT_EQ(2, mIndex++);
+            SkMatrix expectedMatrix;
+            expectedMatrix.setTranslate(100 - SCROLL_X, 100 - SCROLL_Y);
+            EXPECT_EQ(expectedMatrix, getTotalMatrix());
+            EXPECT_EQ(SkRect::MakeLTRB(-85, -80, 295, 300), getLocalBounds(this));
+        }
+        int mIndex = 0;
+    };
+
+    class ProjectionLayer : public SkSurface_Base {
+    public:
+        ProjectionLayer(ProjectionTestCanvas *canvas)
+            : SkSurface_Base(SkImageInfo::MakeN32Premul(LAYER_WIDTH, LAYER_HEIGHT), nullptr)
+            , mCanvas(canvas) {
+        }
+        void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override {
+            EXPECT_EQ(3, mCanvas->mIndex++);
+            EXPECT_EQ(SkRect::MakeLTRB(100 - SCROLL_X, 100 - SCROLL_Y, 300 - SCROLL_X,
+                   300 - SCROLL_Y), getBounds(mCanvas));
+        }
+        SkCanvas* onNewCanvas() override {
+            mCanvas->ref();
+            return mCanvas;
+        }
+        sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override {
+            return sk_sp<SkSurface>();
+        }
+        sk_sp<SkImage> onNewImageSnapshot(SkBudgeted, SkCopyPixelsMode) override {
+            return sk_sp<SkImage>();
+        }
+        void onCopyOnWrite(ContentChangeMode) override {}
+        ProjectionTestCanvas* mCanvas;
+    };
+
+    auto receiverBackground = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+            [](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+        properties.setProjectionReceiver(true);
+        // scroll doesn't apply to background, so undone via translationX/Y
+        // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
+        properties.setTranslationX(SCROLL_X);
+        properties.setTranslationY(SCROLL_Y);
+
+        canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, SkPaint());
+    }, "B"); //B
+    auto projectingRipple = TestUtils::createSkiaNode(0, 0, LAYER_WIDTH, LAYER_HEIGHT,
+            [](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+        properties.setProjectBackwards(true);
+        properties.setClipToBounds(false);
+        canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds
+    }, "R"); //R
+    auto child = TestUtils::createSkiaNode(100, 100, 300, 300,
+            [&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+        canvas.drawRenderNode(projectingRipple.get());
+        canvas.drawArc(0, 0, LAYER_WIDTH, LAYER_HEIGHT, 0.0f, 280.0f, true, SkPaint());
+    }, "C"); //C
+    auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+            [&receiverBackground, &child](RenderProperties& properties,
+            SkiaRecordingCanvas& canvas) {
+        // Set a rect outline for the projecting ripple to be masked against.
+        properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f);
+        canvas.translate(-SCROLL_X, -SCROLL_Y); // Apply scroll (note: bg undoes this internally)
+        canvas.drawRenderNode(receiverBackground.get());
+        canvas.drawRenderNode(child.get());
+    }, "A"); //A
+
+    //prepareTree is required to find, which receivers have backward projected nodes
+    ContextFactory contextFactory;
+    std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
+            renderThread, false, parent.get(), &contextFactory));
+    TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
+    DamageAccumulator damageAccumulator;
+    info.damageAccumulator = &damageAccumulator;
+    info.observer = nullptr;
+    parent->prepareTree(info);
+
+    sk_sp<ProjectionTestCanvas> canvas(new ProjectionTestCanvas());
+    //set a layer after prepareTree to avoid layer logic there
+    child->animatorProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
+    sk_sp<SkSurface> surfaceLayer1(new ProjectionLayer(canvas.get()));
+    child->setLayerSurface(surfaceLayer1);
+    Matrix4 windowTransform;
+    windowTransform.loadTranslate(100, 100, 0);
+    child->getSkiaLayer()->inverseTransformInWindow.loadInverse(windowTransform);
+
+    LayerUpdateQueue layerUpdateQueue;
+    layerUpdateQueue.enqueueLayerWithDamage(child.get(),
+            android::uirenderer::Rect(LAYER_WIDTH, LAYER_HEIGHT));
+    SkiaPipeline::renderLayersImpl(layerUpdateQueue, true);
+    EXPECT_EQ(1, canvas->mIndex);  //assert index 0 is drawn on the layer
+
+    RenderNodeDrawable drawable(parent.get(), canvas.get(), true);
+    canvas->drawDrawable(&drawable);
+    EXPECT_EQ(4, canvas->mIndex);
+
+    // clean up layer pointer, so we can safely destruct RenderNode
+    child->setLayerSurface(nullptr);
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionChildScroll) {
+    /* R is backward projected on B.
+                A
+               / \
+              B   C
+                  |
+                  R
+    */
+    static const int SCROLL_X = 500000;
+    static const int SCROLL_Y = 0;
+    static const int CANVAS_WIDTH = 400;
+    static const int CANVAS_HEIGHT = 400;
+    class ProjectionChildScrollTestCanvas : public SkCanvas {
+    public:
+        ProjectionChildScrollTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
+        void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
+            EXPECT_EQ(0, mIndex++);
+            EXPECT_TRUE(getTotalMatrix().isIdentity());
+        }
+        void onDrawOval(const SkRect&, const SkPaint&) override {
+            EXPECT_EQ(1, mIndex++);
+            EXPECT_EQ(SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), getBounds(this));
+            EXPECT_TRUE(getTotalMatrix().isIdentity());
+        }
+        int mIndex = 0;
+    };
+
+    auto receiverBackground = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+            [](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+        properties.setProjectionReceiver(true);
+        canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, SkPaint());
+    }, "B"); //B
+    auto projectingRipple = TestUtils::createSkiaNode(0, 0, 200, 200,
+            [](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+        // scroll doesn't apply to background, so undone via translationX/Y
+        // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
+        properties.setTranslationX(SCROLL_X);
+        properties.setTranslationY(SCROLL_Y);
+        properties.setProjectBackwards(true);
+        properties.setClipToBounds(false);
+        canvas.drawOval(0, 0, 200, 200, SkPaint());
+    }, "R"); //R
+    auto child = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+            [&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) {
+        // Record time clip will be ignored by projectee
+        canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op);
+
+        canvas.translate(-SCROLL_X, -SCROLL_Y); // Apply scroll (note: bg undoes this internally)
+        canvas.drawRenderNode(projectingRipple.get());
+    }, "C"); //C
+    auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+            [&receiverBackground, &child](RenderProperties& properties,
+            SkiaRecordingCanvas& canvas) {
+        canvas.drawRenderNode(receiverBackground.get());
+        canvas.drawRenderNode(child.get());
+    }, "A"); //A
+
+    //prepareTree is required to find, which receivers have backward projected nodes
+    ContextFactory contextFactory;
+    std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
+            renderThread, false, parent.get(), &contextFactory));
+    TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
+    DamageAccumulator damageAccumulator;
+    info.damageAccumulator = &damageAccumulator;
+    info.observer = nullptr;
+    parent->prepareTree(info);
+
+    sk_sp<ProjectionChildScrollTestCanvas> canvas(new ProjectionChildScrollTestCanvas());
+    RenderNodeDrawable drawable(parent.get(), canvas.get(), true);
+    canvas->drawDrawable(&drawable);
+    EXPECT_EQ(2, canvas->mIndex);
+}
+
+namespace {
+static int drawNode(RenderThread& renderThread, const sp<RenderNode>& renderNode)
+{
+    ContextFactory contextFactory;
+    std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
+            renderThread, false, renderNode.get(), &contextFactory));
+    TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
+    DamageAccumulator damageAccumulator;
+    info.damageAccumulator = &damageAccumulator;
+    info.observer = nullptr;
+    renderNode->prepareTree(info);
+
+    //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
+    ZReorderCanvas canvas(100, 100);
+    RenderNodeDrawable drawable(renderNode.get(), &canvas, false);
+    canvas.drawDrawable(&drawable);
+    return canvas.getIndex();
+}
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectedInMiddle) {
+    /* R is backward projected on B
+                A
+               / \
+              B   C
+                  |
+                  R
+    */
+    auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+            props.setProjectionReceiver(true);
+        } ); //nodeB
+        drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+            drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+    EXPECT_EQ(3, drawNode(renderThread, nodeA));
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectLast) {
+    /* R is backward projected on E
+                  A
+                / | \
+               /  |  \
+              B   C   E
+                  |
+                  R
+    */
+    auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, nullptr); //nodeB
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+            drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //drawn as 2
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+        drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //drawn as 3
+            props.setProjectionReceiver(true);
+        } ); //nodeE
+    }); //nodeA
+    EXPECT_EQ(4, drawNode(renderThread, nodeA));
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderNoReceivable) {
+    /* R is backward projected without receiver
+                A
+               / \
+              B   C
+                  |
+                  R
+    */
+     auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, nullptr); //nodeB
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+            drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+                //not having a projection receiver is an undefined behavior
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+    EXPECT_EQ(2, drawNode(renderThread, nodeA));
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderParentReceivable) {
+    /* R is backward projected on C
+                A
+               / \
+              B   C
+                  |
+                  R
+    */
+     auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, nullptr); //nodeB
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+            props.setProjectionReceiver(true);
+            drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+    EXPECT_EQ(3, drawNode(renderThread, nodeA));
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderSameNodeReceivable) {
+    /* R is backward projected on R
+                A
+               / \
+              B   C
+                  |
+                  R
+    */
+     auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, nullptr); //nodeB
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+            drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+                //having a node that is projected on itself is an undefined/unexpected behavior
+                props.setProjectionReceiver(true);
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+    EXPECT_EQ(2, drawNode(renderThread, nodeA));
+}
+
+//Note: the outcome for this test is different in HWUI
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectedSibling) {
+    /* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed.
+                A
+               /|\
+              / | \
+             B  C  R
+    */
+    auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+            props.setProjectionReceiver(true);
+        } ); //nodeB
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        } ); //nodeC
+        drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+            props.setProjectBackwards(true);
+            props.setClipToBounds(false);
+        } ); //nodeR
+    }); //nodeA
+    EXPECT_EQ(2, drawNode(renderThread, nodeA));
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectedSibling2) {
+    /* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed.
+                A
+                |
+                G
+               /|\
+              / | \
+             B  C  R
+    */
+    auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+            drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+                props.setProjectionReceiver(true);
+            } ); //nodeB
+            drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+            } ); //nodeC
+            drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeG
+    }); //nodeA
+    EXPECT_EQ(3, drawNode(renderThread, nodeA));
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderGrandparentReceivable) {
+    /* R is backward projected on B
+                A
+                |
+                B
+                |
+                C
+                |
+                R
+    */
+    auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+            props.setProjectionReceiver(true);
+            drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+                drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+                    props.setProjectBackwards(true);
+                    props.setClipToBounds(false);
+                } ); //nodeR
+            } ); //nodeC
+        } ); //nodeB
+    }); //nodeA
+    EXPECT_EQ(3, drawNode(renderThread, nodeA));
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderTwoReceivables) {
+    /* B and G are receivables, R is backward projected
+                A
+               / \
+              B   C
+                 / \
+                G   R
+    */
+    auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //B
+            props.setProjectionReceiver(true);
+        } ); //nodeB
+        drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //C
+            drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //G
+                props.setProjectionReceiver(true);
+            } ); //nodeG
+            drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //R
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+    EXPECT_EQ(4, drawNode(renderThread, nodeA));
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderTwoReceivablesLikelyScenario) {
+    /* B and G are receivables, G is backward projected
+                A
+               / \
+              B   C
+                 / \
+                G   R
+    */
+    auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //B
+            props.setProjectionReceiver(true);
+        } ); //nodeB
+        drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //C
+            drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //G
+                props.setProjectionReceiver(true);
+                props.setProjectBackwards(true);
+                props.setClipToBounds(false);
+            } ); //nodeG
+            drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //R
+            } ); //nodeR
+        } ); //nodeC
+    }); //nodeA
+    EXPECT_EQ(4, drawNode(renderThread, nodeA));
+}
+
+RENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderTwoReceivablesDeeper) {
+    /* B and G are receivables, R is backward projected
+                A
+               / \
+              B   C
+                 / \
+                G   D
+                    |
+                    R
+    */
+    auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100,
+            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+        drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //B
+            props.setProjectionReceiver(true);
+        } ); //nodeB
+        drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //C
+            drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //G
+                props.setProjectionReceiver(true);
+            } ); //nodeG
+            drawOrderedNode(&canvas, 4, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //D
+                drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //R
+                    props.setProjectBackwards(true);
+                    props.setClipToBounds(false);
+                } ); //nodeR
+            } ); //nodeD
+        } ); //nodeC
+    }); //nodeA
+    EXPECT_EQ(5, drawNode(renderThread, nodeA));
 }
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index 67fb78a..899758a 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -33,7 +33,7 @@
     SkRect bounds = SkRect::MakeWH(200, 200);
     SkiaDisplayList skiaDL(bounds);
     ASSERT_TRUE(skiaDL.isEmpty());
-    ASSERT_FALSE(skiaDL.mIsProjectionReceiver);
+    ASSERT_FALSE(skiaDL.mProjectionReceiver);
     ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
 }
 
@@ -42,12 +42,13 @@
     SkiaDisplayList skiaDL(bounds);
 
     SkCanvas dummyCanvas;
+    RenderNodeDrawable drawable(nullptr, &dummyCanvas);
     skiaDL.mChildNodes.emplace_back(nullptr, &dummyCanvas);
     skiaDL.mChildFunctors.emplace_back(nullptr, nullptr, &dummyCanvas);
     skiaDL.mMutableImages.push_back(nullptr);
     skiaDL.mVectorDrawables.push_back(nullptr);
     skiaDL.mDrawable->drawAnnotation(bounds, "testAnnotation", nullptr);
-    skiaDL.mIsProjectionReceiver = true;
+    skiaDL.mProjectionReceiver = &drawable;
 
     ASSERT_EQ(skiaDL.mDrawable->getBounds(), bounds);
     ASSERT_FALSE(skiaDL.mChildNodes.empty());
@@ -55,7 +56,7 @@
     ASSERT_FALSE(skiaDL.mMutableImages.empty());
     ASSERT_FALSE(skiaDL.mVectorDrawables.empty());
     ASSERT_FALSE(skiaDL.isEmpty());
-    ASSERT_TRUE(skiaDL.mIsProjectionReceiver);
+    ASSERT_TRUE(skiaDL.mProjectionReceiver);
 
     bounds = SkRect::MakeWH(100, 100);
     skiaDL.reset(bounds);
@@ -66,7 +67,7 @@
     ASSERT_TRUE(skiaDL.mMutableImages.empty());
     ASSERT_TRUE(skiaDL.mVectorDrawables.empty());
     ASSERT_TRUE(skiaDL.isEmpty());
-    ASSERT_FALSE(skiaDL.mIsProjectionReceiver);
+    ASSERT_FALSE(skiaDL.mProjectionReceiver);
 }
 
 TEST(SkiaDisplayList, reuseDisplayList) {
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 89709ee..5440f0f 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -584,6 +584,10 @@
          * @return the same Builder instance.
          */
         public Builder setLegacyStreamType(int streamType) {
+            if (streamType == AudioManager.STREAM_ACCESSIBILITY) {
+                throw new IllegalArgumentException("STREAM_ACCESSIBILITY is not a legacy stream "
+                        + "type that was used for audio playback");
+            }
             return setInternalLegacyStreamType(streamType);
         }
 
@@ -624,12 +628,15 @@
                     mContentType = CONTENT_TYPE_SONIFICATION;
                     break;
                 case AudioSystem.STREAM_TTS:
+                    mContentType = CONTENT_TYPE_SONIFICATION;
+                    break;
+                case AudioSystem.STREAM_ACCESSIBILITY:
                     mContentType = CONTENT_TYPE_SPEECH;
                     break;
                 default:
                     Log.e(TAG, "Invalid stream type " + streamType + " for AudioAttributes");
             }
-            mUsage = usageForLegacyStreamType(streamType);
+            mUsage = usageForStreamType(streamType);
             return this;
         }
 
@@ -842,8 +849,7 @@
         }
     }
 
-    /** @hide */
-    public static int usageForLegacyStreamType(int streamType) {
+    private static int usageForStreamType(int streamType) {
         switch(streamType) {
             case AudioSystem.STREAM_VOICE_CALL:
                 return USAGE_VOICE_COMMUNICATION;
@@ -862,8 +868,9 @@
                 return USAGE_VOICE_COMMUNICATION;
             case AudioSystem.STREAM_DTMF:
                 return USAGE_VOICE_COMMUNICATION_SIGNALLING;
-            case AudioSystem.STREAM_TTS:
+            case AudioSystem.STREAM_ACCESSIBILITY:
                 return USAGE_ASSISTANCE_ACCESSIBILITY;
+            case AudioSystem.STREAM_TTS:
             default:
                 return USAGE_UNKNOWN;
         }
@@ -915,7 +922,6 @@
         switch (aa.getUsage()) {
             case USAGE_MEDIA:
             case USAGE_GAME:
-            case USAGE_ASSISTANCE_ACCESSIBILITY:
             case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
                 return AudioSystem.STREAM_MUSIC;
             case USAGE_ASSISTANCE_SONIFICATION:
@@ -935,6 +941,8 @@
             case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
             case USAGE_NOTIFICATION_EVENT:
                 return AudioSystem.STREAM_NOTIFICATION;
+            case USAGE_ASSISTANCE_ACCESSIBILITY:
+                return AudioSystem.STREAM_ACCESSIBILITY;
             case USAGE_UNKNOWN:
                 return fromGetVolumeControlStream ?
                         AudioManager.USE_DEFAULT_STREAM_TYPE : AudioSystem.STREAM_MUSIC;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index f24bf09..435e6ba 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -335,6 +335,9 @@
     /** @hide Used to identify the volume of audio streams exclusively transmitted through the
      *        speaker (TTS) of the device */
     public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
+    /** Used to identify the volume of audio streams for accessibility prompts */
+    public static final int STREAM_ACCESSIBILITY = AudioSystem.STREAM_ACCESSIBILITY;
+
     /** Number of audio streams */
     /**
      * @deprecated Do not iterate on volume stream type values.
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 384be5c..28c7253 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -63,13 +63,15 @@
     /** Used to identify the volume of audio streams exclusively transmitted through the
      *  speaker (TTS) of the device */
     public static final int STREAM_TTS = 9;
+    /** Used to identify the volume of audio streams for accessibility prompts */
+    public static final int STREAM_ACCESSIBILITY = 10;
     /**
      * @deprecated Use {@link #numStreamTypes() instead}
      */
     public static final int NUM_STREAMS = 5;
 
     // Expose only the getter method publicly so we can change it in the future
-    private static final int NUM_STREAM_TYPES = 10;
+    private static final int NUM_STREAM_TYPES = 11;
     public static final int getNumStreamTypes() { return NUM_STREAM_TYPES; }
 
     public static final String[] STREAM_NAMES = new String[] {
@@ -82,7 +84,8 @@
         "STREAM_BLUETOOTH_SCO",
         "STREAM_SYSTEM_ENFORCED",
         "STREAM_DTMF",
-        "STREAM_TTS"
+        "STREAM_TTS",
+        "STREAM_ACCESSIBILITY"
     };
 
     /*
@@ -773,7 +776,8 @@
         7,  // STREAM_BLUETOOTH_SCO
         7,  // STREAM_SYSTEM_ENFORCED
         11, // STREAM_DTMF
-        11  // STREAM_TTS
+        11, // STREAM_TTS
+        11, // STREAM_ACCESSIBILITY
     };
 
     public static String streamToString(int stream) {
diff --git a/media/java/android/media/MediaHTTPService.java b/media/java/android/media/MediaHTTPService.java
index 2348ab7..52a68bf 100644
--- a/media/java/android/media/MediaHTTPService.java
+++ b/media/java/android/media/MediaHTTPService.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.os.IBinder;
+import android.util.Log;
 
 /** @hide */
 public class MediaHTTPService extends IMediaHTTPService.Stub {
@@ -31,10 +32,10 @@
 
     /* package private */static IBinder createHttpServiceBinderIfNecessary(
             String path) {
-        if (path.startsWith("http://")
-                || path.startsWith("https://")
-                || path.startsWith("widevine://")) {
+        if (path.startsWith("http://") || path.startsWith("https://")) {
             return (new MediaHTTPService()).asBinder();
+        } else if (path.startsWith("widevine://")) {
+            Log.d(TAG, "Widevine classic is no longer supported");
         }
 
         return null;
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 295248c..34d236b 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Gepasmaak (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Hulp en terugvoer"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Kieslys"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index bb50087..d0abbf9 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ብጁ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"እገዛ እና ግብረመልስ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ምናሌ"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 829123c..0eebcd7 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"مخصص (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"المساعدة والتعليقات"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"القائمة"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index 483770f..c0b776e 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Fərdi (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Yardım və rəy"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 5498580a..cbb2271 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagođeni (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-be-rBY/strings.xml b/packages/SettingsLib/res/values-be-rBY/strings.xml
index f233db9..12f103d 100644
--- a/packages/SettingsLib/res/values-be-rBY/strings.xml
+++ b/packages/SettingsLib/res/values-be-rBY/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Карыстальніцкі (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Даведка і водгукі"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index cd77792..23adb5a 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Персонализирано (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Помощ и отзиви"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index a011fcf..09988ed 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"কাস্টম (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"সহায়তা ও মতামত"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"মেনু"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index 1df5ec9..561af92 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagodi (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 92e9005..19382ec 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalitzat (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda i suggeriments"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 8ec531c..5276b3a 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Vlastní (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Nápověda a zpětná vazba"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Nabídka"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index a65c58f..0c56b8d 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tilpasset (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Hjælp og feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 923eca1..60f373b 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Benutzerdefiniert (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Hilfe &amp; Feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 3c0247d..032d73d 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Προσαρμοσμένη (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Βοήθεια και σχόλια"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Μενού"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 8ed7444..57738e8 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Help &amp; feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 8ed7444..57738e8 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Help &amp; feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 8ed7444..57738e8 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Help &amp; feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index cdfbc01..e0b5bb7 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Ayuda y comentarios"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 2a21d22..259e7fb 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Ayuda y sugerencias"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index 644bf59..7d70efe 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Kohandatud (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Abi ja tagasiside"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menüü"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index 2217611..952fda8 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Pertsonalizatua (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Laguntza eta iritziak"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menua"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 88ed7fa..e998b69 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"سفارشی (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"راهنما و بازخورد"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"منو"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index d26fc05..bf96b59 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Muokattu (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Ohje ja palaute"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Valikko"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 58aab1d..e2eb10d 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personnalisée (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Aide et commentaires"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 91bbaf0..282ae4a 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personnalisé (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Aide et commentaires"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index b717382..f4bb7ad 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Axuda e suxestións"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index 5605189..1cded3d 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"કસ્ટમ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"સહાય અને પ્રતિસાદ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"મેનુ"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index d579ec4..a2a6e04 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"कस्टम (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"सहायता और फ़ीडबैक"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"मेनू"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 94229b1..76f04bd 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Prilagođeno (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Izbornik"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 34f06e5..f5f6916 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Egyéni (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Súgó és visszajelzés"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 9428e17..6dcb745 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Հատուկ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Օգնություն և հետադարձ կապ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Ընտրացանկ"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index a382e37..07241b5 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"(<xliff:g id="DENSITYDPI">%d</xliff:g>) khusus"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Bantuan &amp; masukan"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index 44517a8..8e8307b 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Sérsniðið (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Hjálp og ábendingar"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Valmynd"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 7a32827..d894ccf 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizzato (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Guida e feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 2e85770..2ee38ef 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"מותאם אישית (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"עזרה ומשוב"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"תפריט"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 00e323c..8b2d784 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -343,4 +343,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"カスタム(<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"ヘルプとフィードバック"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"メニュー"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 2b9e8cb..609cb33 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"მორგებული (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"დახმარება და გამოხმაურება"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"მენიუ"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 0037c11..92d7783 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Арнаулы (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Анықтама және пікір"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Mәзір"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 235ea6a..46cc6ce 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ផ្ទាល់ខ្លួន (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"ជំនួយ និងមតិស្ថាបនា"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ម៉ឺនុយ"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index d7c8d03..cf8f382 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ಕಸ್ಟಮ್ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ಮೆನು"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 21bbc3f..03c0edf 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"맞춤(<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"고객센터"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"메뉴"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index ca716cae..a2eb86d 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Ыңгайлаштырылган (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Жардам жана жооп пикир"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index 0108c2c..41a8eef 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ປັບແຕ່ງເອງ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"ຊ່ວຍເຫຼືອ &amp; ຄຳຕິຊົມ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ເມນູ"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 154864f..6930c7a 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tinkintas (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Pagalba ir atsiliepimai"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meniu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index df91cb1..7734881 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Pielāgots (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Palīdzība un atsauksmes"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Izvēlne"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index 42bc33f..711b949 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Приспособен (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Помош и повратни информации"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Мени"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index a6017d5..8bcbf79 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ഇഷ്ടാനുസൃതം ( <xliff:g id="DENSITYDPI">%d</xliff:g> )"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"സഹായവും പ്രതികരണവും"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"മെനു"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index cb6327a..4fa3779 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Тогтмол утга (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Тусламж, санал хүсэлт"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Цэс"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index b6adb4f..20f64fe 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"सानुकूल करा (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"मदत आणि अभिप्राय"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"मेनू"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index 9886d3e..cf77254 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tersuai (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Bantuan &amp; maklum balas"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 935ad40..9db8348 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"စိတ်ကြိုက် (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"အကူအညီနှင့် အကြံပြုချက်"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"မီနူး"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 18b6f60..cc4e567 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Egendefinert (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Hjelp og tilbakemelding"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meny"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 478e19d..a8a918b 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"अनुकूलन (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"मद्दत र प्रतिक्रिया"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"मेनु"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 3b84313..8bb4579 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Aangepast (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Help en feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index b678aac..f19ba3e 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"ਮਦਦ ਅਤੇ ਪ੍ਰਤੀਕਰਮ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ਮੀਨੂ"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 77a23f2..4db3e6e 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Niestandardowe (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomoc i opinie"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 588ca67..7855beb 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizada (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda e feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 763cb70..2c366c6 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizado (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda e comentários"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 588ca67..7855beb 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizada (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda e feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 6a2122a..5d0b965 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personalizat (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Ajutor și feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meniu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 1f192c1..d301ce1 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Другой (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Справка/отзыв"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index e415544..f21793b 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"අභිරුචි (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"උදව් සහ ප්‍රතිපෝෂණ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"මෙනුව"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 7e636fe7..b478ecf 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Vlastné (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomocník a spätná väzba"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Ponuka"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 78fa3fd..b9da0eb 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Po meri (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomoč in povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index ad4cf61..c17376b 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"I personalizuar (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Ndihma dhe komentet"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyja"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 02eb615..2cf68a5 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Прилагођени (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Помоћ и повратне информације"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Мени"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index a936c3e..975a4aa 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Anpassad (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Hjälp och feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meny"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 25f79b6..f14cbdd 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Kiwango maalum (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Usaidizi na maoni"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index 9e9e92c..2640122 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"தனிப்பயன் (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"உதவி &amp; கருத்து"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"மெனு"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 27f8e09..60a4d72 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"అనుకూలం (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"సహాయం &amp; అభిప్రాయం"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"మెను"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 6005972..fbb67bc 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"กำหนดเอง (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"ความช่วยเหลือและความคิดเห็น"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"เมนู"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index e9feded..50c43bb 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Custom (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Tulong at feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 0e73b7b..c5ae71c 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Özel (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Yardım ve geri bildirim"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 1015e1c..b538545 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Спеціальний масштаб (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Довідка й відгуки"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 61dc5ab..0b5e8a0 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"حسب ضرورت (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"مدد اور تاثرات"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"مینو"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index a6f9ab8..8d1056a 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Moslashtirilgan (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Yordam va fikr-mulohaza"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index f09e0e5..21e5b75 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Tùy chỉnh (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Trợ giúp và phản hồi"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 7268dcd..ba657c6 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自定义 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"帮助和反馈"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"菜单"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index ea03fb6..60f56f1 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自訂 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"說明和意見反映"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"選單"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index f17b523..6bb7308 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"自訂 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"說明與意見回饋"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"選單"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 1fc551f..6714b27 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -341,4 +341,6 @@
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Ngokwezifiso (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Usizo nempendulo"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Imenyu"</string>
+    <!-- no translation found for time_zone_gmt (2587097992671450782) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/doze/DozeProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/doze/DozeProvider.java
new file mode 100644
index 0000000..688df46
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/doze/DozeProvider.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.plugins.doze;
+
+import android.app.PendingIntent;
+import android.content.Context;
+
+import com.android.systemui.plugins.Plugin;
+
+/**
+ * Provides a {@link DozeUi}.
+ */
+public interface DozeProvider extends Plugin {
+
+    String ACTION = "com.android.systemui.action.PLUGIN_DOZE";
+    int VERSION = 1;
+
+    /**
+     * Caution: Even if this is called, the DozeUi provided may still be in use until it transitions
+     * to DozeState.FINISH
+     */
+    @Override
+    default void onDestroy() {
+    }
+
+    /**
+     * @return the plugin's implementation of DozeUi.
+     */
+    DozeUi provideDozeUi(Context context, DozeMachine machine, WakeLock wakeLock);
+
+    /**
+     * If true, the plugin allows the default pulse triggers to fire, otherwise they are disabled.
+     */
+    default boolean allowDefaultPulseTriggers() {
+        return false;
+    }
+
+    /**
+     * Ui for use in DozeMachine.
+     */
+    interface DozeUi {
+        /** Called whenever the DozeMachine state transitions */
+        void transitionTo(DozeState oldState, DozeState newState);
+    }
+
+    /** WakeLock wrapper for testability */
+    interface WakeLock {
+        /** @see android.os.PowerManager.WakeLock#acquire() */
+        void acquire();
+        /** @see android.os.PowerManager.WakeLock#release() */
+        void release();
+        /** @see android.os.PowerManager.WakeLock#wrap(Runnable) */
+        Runnable wrap(Runnable r);
+    }
+
+    /** Plugin version of the DozeMachine's state */
+    enum DozeState {
+        /** Default state. Transition to INITIALIZED to get Doze going. */
+        UNINITIALIZED,
+        /** Doze components are set up. Followed by transition to DOZE or DOZE_AOD. */
+        INITIALIZED,
+        /** Regular doze. Device is asleep and listening for pulse triggers. */
+        DOZE,
+        /** Always-on doze. Device is asleep, showing UI and listening for pulse triggers. */
+        DOZE_AOD,
+        /** Pulse has been requested. Device is awake and preparing UI */
+        DOZE_REQUEST_PULSE,
+        /** Pulse is showing. Device is awake and showing UI. */
+        DOZE_PULSING,
+        /** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */
+        DOZE_PULSE_DONE,
+        /** Doze is done. DozeService is finished. */
+        FINISH,
+        /** WakeUp. */
+        WAKE_UP,
+    }
+
+    /** Plugin interface for the doze machine. */
+    interface DozeMachine {
+        /** Request that the DozeMachine transitions to {@code state} */
+        void requestState(DozeState state);
+
+        /** Request that the PendingIntent is sent. */
+        void requestSendIntent(PendingIntent intent);
+    }
+}
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 502a94e..a1a8f8d 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -198,13 +198,13 @@
     <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"تشغيل وضع الطائرة."</string>
     <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"تم إيقاف وضع الطائرة."</string>
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"تم تشغيل وضع الطائرة."</string>
-    <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"تم تشغيل الرجاء عدم الإزعاج، الأولوية فقط."</string>
-    <string name="accessibility_quick_settings_dnd_none_on" msgid="6882582132662613537">"تم تشغيل الرجاء عدم الإزعاج، كتم الصوت تمامًا."</string>
-    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"تم تشغيل الرجاء عدم الإزعاج، التنبيهات فقط."</string>
+    <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"تم تشغيل \"عدم الإزعاج، الأولوية فقط\"."</string>
+    <string name="accessibility_quick_settings_dnd_none_on" msgid="6882582132662613537">"تم تشغيل \"عدم الإزعاج، كتم الصوت تمامًا\"."</string>
+    <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"تم تشغيل \"عدم الإزعاج، التنبيهات فقط\"."</string>
     <string name="accessibility_quick_settings_dnd" msgid="6607873236717185815">"الرجاء عدم الإزعاج."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"تم تعطيل \"الرجاء عدم الإزعاج\"."</string>
     <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"تم تعطيل \"الرجاء عدم الإزعاج\"."</string>
-    <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"تم تشغيل \"الرجاء عدم الإزعاج\"."</string>
+    <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"تم تشغيل \"عدم الإزعاج\"."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="6341675755803320038">"البلوتوث."</string>
     <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"إيقاف البلوتوث."</string>
     <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"تشغيل البلوتوث."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index f482caaa..97f3926 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -342,7 +342,7 @@
     <string name="description_target_search" msgid="3091587249776033139">"खोजें"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए ऊपर स्‍लाइड करें."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए बाएं स्‍लाइड करें."</string>
-    <string name="zen_priority_introduction" msgid="3070506961866919502">"आपको आपके द्वारा निर्दिष्ट किए गए अलार्म, रिमाइंडर्स, ईवेंट और कॉलर को छोड़कर अन्य ध्वनियों और कंपनों के द्वारा परेशान नहीं किया जाएगा."</string>
+    <string name="zen_priority_introduction" msgid="3070506961866919502">"आपको आपके द्वारा निर्दिष्ट किए गए अलार्म, रिमाइंडर्स, इवेंट और कॉलर को छोड़कर अन्य ध्वनियों और कंपनों के द्वारा परेशान नहीं किया जाएगा."</string>
     <string name="zen_priority_customize_button" msgid="7948043278226955063">"कस्टमाइज़ करें"</string>
     <string name="zen_silence_introduction_voice" msgid="2284540992298200729">"इससे अलार्म, संगीत, वीडियो और गेम सहित सभी ध्‍वनियां और कंपन अवरुद्ध हो जाते हैं. आप अभी भी फ़ोन काॅल कर सकेंगे."</string>
     <string name="zen_silence_introduction" msgid="3137882381093271568">"इससे अलार्म, संगीत, वीडियो और गेम सहित सभी ध्वनियां और कंपन अवरुद्ध हो जाते हैं."</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 8217ee5..29f8875 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -164,8 +164,8 @@
     <string name="accessibility_settings_button" msgid="799583911231893380">"Systeeminstellingen."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Meldingen."</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Melding wissen"</string>
-    <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ingeschakeld."</string>
-    <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Verbinding maken met GPS."</string>
+    <string name="accessibility_gps_enabled" msgid="3511469499240123019">"gps ingeschakeld."</string>
+    <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Verbinding maken met gps."</string>
     <string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter ingeschakeld."</string>
     <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Belsoftware trilt."</string>
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Belsoftware stil."</string>
@@ -241,8 +241,8 @@
     <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Hervatten"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Geen internetverbinding"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Verbonden via wifi"</string>
-    <string name="gps_notification_searching_text" msgid="8574247005642736060">"Zoeken naar GPS"</string>
-    <string name="gps_notification_found_text" msgid="4619274244146446464">"Locatie bepaald met GPS"</string>
+    <string name="gps_notification_searching_text" msgid="8574247005642736060">"Zoeken naar gps"</string>
+    <string name="gps_notification_found_text" msgid="4619274244146446464">"Locatie bepaald met gps"</string>
     <string name="accessibility_location_active" msgid="2427290146138169014">"Locatieverzoeken actief"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle meldingen wissen."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -376,7 +376,7 @@
     <string name="guest_exit_guest_dialog_message" msgid="4155503224769676625">"Alle apps en gegevens in deze sessie worden verwijderd."</string>
     <string name="guest_exit_guest_dialog_remove" msgid="7402231963862520531">"Verwijderen"</string>
     <string name="guest_wipe_session_title" msgid="6419439912885956132">"Welkom terug, gast!"</string>
-    <string name="guest_wipe_session_message" msgid="8476238178270112811">"Wilt u doorgaan met je sessie?"</string>
+    <string name="guest_wipe_session_message" msgid="8476238178270112811">"Wil je doorgaan met je sessie?"</string>
     <string name="guest_wipe_session_wipe" msgid="5065558566939858884">"Opnieuw starten"</string>
     <string name="guest_wipe_session_dontwipe" msgid="1401113462524894716">"Ja, doorgaan"</string>
     <string name="guest_notification_title" msgid="1585278533840603063">"Gastgebruiker"</string>
diff --git a/packages/SystemUI/res/values-pl/strings_car.xml b/packages/SystemUI/res/values-pl/strings_car.xml
index d6e02d6..dbb0373 100644
--- a/packages/SystemUI/res/values-pl/strings_car.xml
+++ b/packages/SystemUI/res/values-pl/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Jedź bezpiecznie"</string>
-    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Uważnie obserwuj warunki na drodze i zawsze przestrzegaj obowiązującego prawa. Wskazówki mogą być niedokładne, niekompletne, niebezpieczne, nieprzydatne lub niezgodne z prawem, mogą też obejmować przekraczanie obszarów administracyjnych. Informacje o firmach również mogą być niedokładne lub niekompletne. Dane nie są podawane w czasie rzeczywistym. Nie ma gwarancji, że dane o lokalizacji są dokładne. Podczas prowadzenia samochodu nie obsługuj urządzenia mobilnego ani nie używaj aplikacji nieprzeznaczonych na Android Auto."</string>
+    <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Uważnie obserwuj warunki na drodze i zawsze przestrzegaj obowiązującego prawa. Wskazówki mogą być niedokładne, niekompletne, niebezpieczne, nieprzydatne lub niezgodne z prawem, mogą też obejmować przekraczanie obszarów administracyjnych. Informacje o firmach również mogą być niedokładne lub niekompletne. Dane nie są podawane w czasie rzeczywistym. Nie ma gwarancji, że dane o lokalizacji są dokładne. Podczas prowadzenia samochodu nie obsługuj urządzenia mobilnego ani nie używaj aplikacji nieprzeznaczonych na Androida Auto."</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 6802fd7..b207984 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -29,6 +29,7 @@
 import android.os.UserHandle;
 import android.util.Log;
 
+import com.android.systemui.doze.DozeFactory;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyboard.KeyboardUI;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -76,7 +77,8 @@
             PipUI.class,
             ShortcutKeyDispatcher.class,
             VendorServices.class,
-            LatencyTester.class
+            LatencyTester.class,
+            DozeFactory.Initializer.class,
     };
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 4cfc811..5b10756 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -17,19 +17,52 @@
 package com.android.systemui.doze;
 
 import android.app.Application;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.hardware.SensorManager;
 import android.os.Handler;
 import android.os.PowerManager;
+import android.os.SystemClock;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIApplication;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.plugins.doze.DozeProvider;
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 public class DozeFactory {
 
+    private static DozeFactory sInstance;
+
+    private DozeProvider mDozePlugin;
+
+    /** Returns the singleton instance. */
+    public static DozeFactory getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new DozeFactory();
+            PluginManager.getInstance(context).addPluginListener(DozeProvider.ACTION,
+                    new PluginListener<DozeProvider>() {
+                        @Override
+                        public void onPluginConnected(DozeProvider plugin) {
+                            sInstance.mDozePlugin = plugin;
+                        }
+
+                        @Override
+                        public void onPluginDisconnected(DozeProvider plugin) {
+                            if (sInstance.mDozePlugin == plugin) {
+                                sInstance.mDozePlugin = null;
+                            }
+                        }
+                    },
+                    DozeProvider.VERSION, false /* Only one */);
+        }
+        return sInstance;
+    }
+
     /** Creates a DozeMachine with its parts for {@code dozeService}. */
-    public static DozeMachine assembleMachine(DozeService dozeService) {
+    public DozeMachine assembleMachine(DozeService dozeService) {
         Context context = dozeService;
         SensorManager sensorManager = context.getSystemService(SensorManager.class);
         PowerManager powerManager = context.getSystemService(PowerManager.class);
@@ -43,14 +76,103 @@
 
         DozeMachine machine = new DozeMachine(dozeService, params, wakeLock);
         machine.setParts(new DozeMachine.Part[]{
-                new DozeTriggers(context, machine, host, config, params,
-                        sensorManager, handler, wakeLock),
-                new DozeUi(context, machine, wakeLock, host),
+                createDozeTriggers(context, sensorManager, host, config, params, handler, wakeLock,
+                        machine),
+                createDozeUi(context, host, wakeLock, machine),
         });
 
         return machine;
     }
 
+    private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
+            DozeHost host, AmbientDisplayConfiguration config, DozeParameters params,
+            Handler handler, WakeLock wakeLock, DozeMachine machine) {
+        boolean allowPulseTriggers = mDozePlugin == null || mDozePlugin.allowDefaultPulseTriggers();
+        return new DozeTriggers(context, machine, host, config, params,
+                sensorManager, handler, wakeLock, allowPulseTriggers);
+    }
+
+    private DozeMachine.Part createDozeUi(Context context, DozeHost host, WakeLock wakeLock,
+            DozeMachine machine) {
+        if (mDozePlugin != null) {
+            DozeProvider.DozeUi dozeUi = mDozePlugin.provideDozeUi(context,
+                    pluginMachine(context, machine, host),
+                    wakeLock);
+            return (oldState, newState) -> {
+                dozeUi.transitionTo(pluginState(oldState),
+                        pluginState(newState));
+            };
+        } else {
+            return new DozeUi(context, machine, wakeLock, host);
+        }
+    }
+
+    private DozeProvider.DozeMachine pluginMachine(Context context, DozeMachine machine,
+            DozeHost host) {
+        return new DozeProvider.DozeMachine() {
+            @Override
+            public void requestState(DozeProvider.DozeState state) {
+                if (state == DozeProvider.DozeState.WAKE_UP) {
+                    PowerManager pm = context.getSystemService(PowerManager.class);
+                    pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:NODOZE");
+                    return;
+                }
+                machine.requestState(implState(state));
+            }
+
+            @Override
+            public void requestSendIntent(PendingIntent intent) {
+                host.startPendingIntentDismissingKeyguard(intent);
+            }
+        };
+    }
+
+    private DozeMachine.State implState(DozeProvider.DozeState s) {
+        switch (s) {
+            case UNINITIALIZED:
+                return DozeMachine.State.UNINITIALIZED;
+            case INITIALIZED:
+                return DozeMachine.State.INITIALIZED;
+            case DOZE:
+                return DozeMachine.State.DOZE;
+            case DOZE_AOD:
+                return DozeMachine.State.DOZE_AOD;
+            case DOZE_REQUEST_PULSE:
+                return DozeMachine.State.DOZE_REQUEST_PULSE;
+            case DOZE_PULSING:
+                return DozeMachine.State.DOZE_PULSING;
+            case DOZE_PULSE_DONE:
+                return DozeMachine.State.DOZE_PULSE_DONE;
+            case FINISH:
+                return DozeMachine.State.FINISH;
+            default:
+                throw new IllegalArgumentException("Unknown state: " + s);
+        }
+    }
+
+    private DozeProvider.DozeState pluginState(DozeMachine.State s) {
+        switch (s) {
+            case UNINITIALIZED:
+                return DozeProvider.DozeState.UNINITIALIZED;
+            case INITIALIZED:
+                return DozeProvider.DozeState.INITIALIZED;
+            case DOZE:
+                return DozeProvider.DozeState.DOZE;
+            case DOZE_AOD:
+                return DozeProvider.DozeState.DOZE_AOD;
+            case DOZE_REQUEST_PULSE:
+                return DozeProvider.DozeState.DOZE_REQUEST_PULSE;
+            case DOZE_PULSING:
+                return DozeProvider.DozeState.DOZE_PULSING;
+            case DOZE_PULSE_DONE:
+                return DozeProvider.DozeState.DOZE_PULSE_DONE;
+            case FINISH:
+                return DozeProvider.DozeState.FINISH;
+            default:
+                throw new IllegalArgumentException("Unknown state: " + s);
+        }
+    }
+
     private static DozeHost getHost(DozeService service) {
         Application appCandidate = service.getApplication();
         final SystemUIApplication app = (SystemUIApplication) appCandidate;
@@ -58,7 +180,7 @@
     }
 
     /** A wrapper around {@link PowerManager.WakeLock} for testability. */
-    public static class WakeLock {
+    public static class WakeLock implements DozeProvider.WakeLock {
         private final PowerManager.WakeLock mInner;
 
         public WakeLock(PowerManager.WakeLock inner) {
@@ -80,4 +202,13 @@
             return mInner.wrap(runnable);
         }
     }
+
+    /** Hack: We need to initialize the plugin listener before doze actually starts.
+     * This will be unnecessary once we have proper one-shot support */
+    public static class Initializer extends SystemUI {
+        @Override
+        public void start() {
+            getInstance(mContext);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index fb940b5..e081b53 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -17,6 +17,7 @@
 package com.android.systemui.doze;
 
 import android.annotation.NonNull;
+import android.app.PendingIntent;
 
 /**
  * Interface the doze service uses to communicate with the rest of system UI.
@@ -32,14 +33,16 @@
     boolean isNotificationLightOn();
     boolean isPulsingBlocked();
 
-    public interface Callback {
-        void onNewNotifications();
-        void onBuzzBeepBlinked();
-        void onNotificationLight(boolean on);
-        void onPowerSaveChanged(boolean active);
+    void startPendingIntentDismissingKeyguard(PendingIntent intent);
+
+    interface Callback {
+        default void onNewNotifications() {}
+        default void onBuzzBeepBlinked() {}
+        default void onNotificationLight(boolean on) {}
+        default void onPowerSaveChanged(boolean active) {}
     }
 
-    public interface PulseCallback {
+    interface PulseCallback {
         void onPulseStarted();
         void onPulseFinished();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 94cbdd4..78b96b3 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -38,7 +38,7 @@
 
         setWindowless(true);
 
-        mDozeMachine = DozeFactory.assembleMachine(this);
+        mDozeMachine = DozeFactory.getInstance(getApplication()).assembleMachine(this);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 9f26b0c..84b22ea 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -58,6 +58,7 @@
     private final SensorManager mSensorManager;
     private final Handler mHandler;
     private final DozeFactory.WakeLock mWakeLock;
+    private final boolean mAllowPulseTriggers;
     private final UiModeManager mUiModeManager;
     private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
 
@@ -68,7 +69,7 @@
     public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
             AmbientDisplayConfiguration config,
             DozeParameters dozeParameters, SensorManager sensorManager, Handler handler,
-            DozeFactory.WakeLock wakeLock) {
+            DozeFactory.WakeLock wakeLock, boolean allowPulseTriggers) {
         mContext = context;
         mMachine = machine;
         mDozeHost = dozeHost;
@@ -77,6 +78,7 @@
         mSensorManager = sensorManager;
         mHandler = handler;
         mWakeLock = wakeLock;
+        mAllowPulseTriggers = allowPulseTriggers;
         mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters, config,
                 wakeLock, this::onSensor);
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
@@ -149,7 +151,7 @@
 
     private void requestPulse(final int reason, boolean performedProxCheck) {
         Assert.isMainThread();
-        if (mPulsePending || !canPulse()) {
+        if (mPulsePending || !mAllowPulseTriggers || !canPulse()) {
             return;
         }
 
@@ -307,20 +309,11 @@
 
     private DozeHost.Callback mHostCallback = new DozeHost.Callback() {
         @Override
-        public void onNewNotifications() {
-        }
-
-        @Override
         public void onBuzzBeepBlinked() {
             onNotification();
         }
 
         @Override
-        public void onNotificationLight(boolean on) {
-
-        }
-
-        @Override
         public void onPowerSaveChanged(boolean active) {
             if (active) {
                 onPowerSave();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 5bfc17f..9b48e4d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -104,8 +104,8 @@
         int currentUserId = UserHandle.USER_CURRENT;
         updateCurrentQuietProfilesCache(currentUserId);
         SystemServicesProxy ssp = Recents.getSystemServices();
-        mRawTasks = new ArrayList<>(ssp.getRecentTasks(ActivityManager.getMaxRecentTasksStatic(),
-                currentUserId, includeFrontMostExcludedTask, mCurrentQuietProfiles));
+        mRawTasks = ssp.getRecentTasks(ActivityManager.getMaxRecentTasksStatic(),
+                currentUserId, includeFrontMostExcludedTask, mCurrentQuietProfiles);
 
         // Since the raw tasks are given in most-recent to least-recent order, we need to reverse it
         Collections.reverse(mRawTasks);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index c4fb21e..6f13ba5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -5167,5 +5167,10 @@
             return mNotificationLightOn;
         }
 
+        @Override
+        public void startPendingIntentDismissingKeyguard(PendingIntent intent) {
+            PhoneStatusBar.this.startPendingIntentDismissingKeyguard(intent);
+        }
+
     }
 }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index de70026..5eceb9f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -5342,6 +5342,7 @@
     // notify only this one new request of the current state
     protected void notifyNetworkCallback(NetworkAgentInfo nai, NetworkRequestInfo nri) {
         int notifyType = ConnectivityManager.CALLBACK_AVAILABLE;
+        mHandler.removeMessages(EVENT_TIMEOUT_NETWORK_REQUEST, nri);
         if (nri.mPendingIntent == null) {
             callCallbackForRequest(nri, nai, notifyType, 0);
         } else {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index f4ddc06..6701431 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -249,16 +249,13 @@
         try {
             randomLockSeed = SecureRandom.getInstance("SHA1PRNG").generateSeed(40);
             String newPassword = String.valueOf(HexEncoding.encode(randomLockSeed));
-            tieProfileLockToParent(managedUserId, newPassword);
             setLockPasswordInternal(newPassword, managedUserPassword, managedUserId);
             // We store a private credential for the managed user that's unlocked by the primary
             // account holder's credential. As such, the user will never be prompted to enter this
             // password directly, so we always store a password.
             setLong(LockPatternUtils.PASSWORD_TYPE_KEY,
                     DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, managedUserId);
-        } catch (KeyStoreException e) {
-            // Bug: 32490092
-            Slog.e(TAG, "Not able to set keys to keystore", e);
+            tieProfileLockToParent(managedUserId, newPassword);
         } catch (NoSuchAlgorithmException | RemoteException e) {
             Slog.e(TAG, "Fail to tie managed profile", e);
             // Nothing client can do to fix this issue, so we do not throw exception out
@@ -779,7 +776,6 @@
     }
 
     private void unlockChildProfile(int profileHandle) throws RemoteException {
-        if (DEBUG) Slog.v(TAG, "Unlock child profile");
         try {
             doVerifyPassword(getDecryptedPasswordForTiedProfile(profileHandle), false,
                     0 /* no challenge */, profileHandle, null /* progressCallback */);
@@ -1039,7 +1035,7 @@
         }
     }
 
-    private void tieProfileLockToParent(int userId, String password) throws KeyStoreException {
+    private void tieProfileLockToParent(int userId, String password) {
         if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
         byte[] randomLockSeed = password.getBytes(StandardCharsets.UTF_8);
         byte[] encryptionResult;
@@ -1081,7 +1077,7 @@
                 keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId);
             }
         } catch (CertificateException | UnrecoverableKeyException
-                | IOException | BadPaddingException | IllegalBlockSizeException
+                | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException
                 | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
             throw new RuntimeException("Failed to encrypt key", e);
         }
@@ -1223,11 +1219,7 @@
         } finally {
             if (managedUserId != -1 && managedUserDecryptedPassword != null) {
                 if (DEBUG) Slog.v(TAG, "Restore tied profile lock");
-                try {
-                    tieProfileLockToParent(managedUserId, managedUserDecryptedPassword);
-                } catch (KeyStoreException e) {
-                    throw new RuntimeException("Failed to tie profile lock", e);
-                }
+                tieProfileLockToParent(managedUserId, managedUserDecryptedPassword);
             }
         }
     }
diff --git a/services/core/java/com/android/server/accounts/AccountsDb.java b/services/core/java/com/android/server/accounts/AccountsDb.java
index cb594f6..a160b3a 100644
--- a/services/core/java/com/android/server/accounts/AccountsDb.java
+++ b/services/core/java/com/android/server/accounts/AccountsDb.java
@@ -54,7 +54,7 @@
     private static final String DATABASE_NAME = "accounts.db";
     private static final int PRE_N_DATABASE_VERSION = 9;
     private static final int CE_DATABASE_VERSION = 10;
-    private static final int DE_DATABASE_VERSION = 1;
+    private static final int DE_DATABASE_VERSION = 2; // Added visibility support in O.
 
 
     static final String TABLE_ACCOUNTS = "accounts";
@@ -73,6 +73,11 @@
     private static final String AUTHTOKENS_TYPE = "type";
     private static final String AUTHTOKENS_AUTHTOKEN = "authtoken";
 
+    private static final String TABLE_VISIBILITY = "visibility";
+    private static final String VISIBILITY_ACCOUNTS_ID = "accounts_id";
+    private static final String VISIBILITY_UID = "_uid";
+    private static final String VISIBILITY_VALUE = "value";
+
     private static final String TABLE_GRANTS = "grants";
     private static final String GRANTS_ACCOUNTS_ID = "accounts_id";
     private static final String GRANTS_AUTH_TOKEN_TYPE = "auth_token_type";
@@ -153,14 +158,12 @@
             + " AND " + ACCOUNTS_NAME + "=?"
             + " AND " + ACCOUNTS_TYPE + "=?";
 
-    private static final String SELECTION_AUTHTOKENS_BY_ACCOUNT =
-            AUTHTOKENS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)";
+    private static final String SELECTION_ACCOUNTS_ID_BY_ACCOUNT =
+        "accounts_id=(select _id FROM accounts WHERE name=? AND type=?)";
 
-    private static final String[] COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN = {AUTHTOKENS_TYPE,
-            AUTHTOKENS_AUTHTOKEN};
+    private static final String[] COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN =
+            {AUTHTOKENS_TYPE, AUTHTOKENS_AUTHTOKEN};
 
-    private static final String SELECTION_USERDATA_BY_ACCOUNT =
-            EXTRAS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)";
     private static final String[] COLUMNS_EXTRAS_KEY_AND_VALUE = {EXTRAS_KEY, EXTRAS_VALUE};
 
     private static final String ACCOUNT_ACCESS_GRANTS = ""
@@ -334,7 +337,7 @@
         HashMap<String, String> authTokensForAccount = new HashMap<>();
         Cursor cursor = db.query(CE_TABLE_AUTHTOKENS,
                 COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN,
-                SELECTION_AUTHTOKENS_BY_ACCOUNT,
+                SELECTION_ACCOUNTS_ID_BY_ACCOUNT,
                 new String[] {account.name, account.type},
                 null, null, null);
         try {
@@ -438,7 +441,7 @@
         String[] selectionArgs = {account.name, account.type};
         try (Cursor cursor = db.query(CE_TABLE_EXTRAS,
                 COLUMNS_EXTRAS_KEY_AND_VALUE,
-                SELECTION_USERDATA_BY_ACCOUNT,
+                SELECTION_ACCOUNTS_ID_BY_ACCOUNT,
                 selectionArgs,
                 null, null, null)) {
             while (cursor.moveToNext()) {
@@ -523,6 +526,8 @@
             createSharedAccountsTable(db);
             createAccountsDeletionTrigger(db);
             createDebugTable(db);
+            createAccountsVisibilityTable(db);
+            createAccountsDeletionVisibilityCleanupTrigger(db);
         }
 
         private void createSharedAccountsTable(SQLiteDatabase db) {
@@ -551,6 +556,14 @@
                     +   "," + GRANTS_GRANTEE_UID + "))");
         }
 
+        private void createAccountsVisibilityTable(SQLiteDatabase db) {
+            db.execSQL("CREATE TABLE " + TABLE_VISIBILITY + " ( "
+                  + VISIBILITY_ACCOUNTS_ID + " INTEGER NOT NULL, "
+                  + VISIBILITY_UID + " TEXT NOT NULL, "
+                  + VISIBILITY_VALUE + " INTEGER, "
+                  + "PRIMARY KEY(" + VISIBILITY_ACCOUNTS_ID + "," + VISIBILITY_UID + "))");
+        }
+
         static void createDebugTable(SQLiteDatabase db) {
             db.execSQL("CREATE TABLE " + TABLE_DEBUG + " ( "
                     + ACCOUNTS_ID + " INTEGER,"
@@ -563,10 +576,26 @@
                     + DEBUG_TABLE_TIMESTAMP + ")");
         }
 
+        private void createAccountsDeletionVisibilityCleanupTrigger(SQLiteDatabase db) {
+            db.execSQL(""
+                   + " CREATE TRIGGER "
+                   + TABLE_ACCOUNTS + "DeleteVisibility DELETE ON " + TABLE_ACCOUNTS
+                   + " BEGIN"
+                   + "   DELETE FROM " + TABLE_VISIBILITY
+                   + "     WHERE " + VISIBILITY_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
+                   + " END");
+        }
+
         @Override
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
             Log.i(TAG, "upgrade from version " + oldVersion + " to version " + newVersion);
 
+            if (oldVersion == 1) {
+              createAccountsVisibilityTable(db);
+              createAccountsDeletionVisibilityCleanupTrigger(db);
+              ++oldVersion;
+            }
+
             if (oldVersion != newVersion) {
                 Log.e(TAG, "failed to upgrade version " + oldVersion + " to version " + newVersion);
             }
@@ -861,6 +890,84 @@
                 new String[] {Integer.toString(uid)}) > 0;
     }
 
+    boolean setAccountVisibility(long accountId, int uid, int visibility) {
+        SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+        ContentValues values = new ContentValues();
+        values.put(VISIBILITY_ACCOUNTS_ID, String.valueOf(accountId));
+        values.put(VISIBILITY_UID, String.valueOf(uid));
+        values.put(VISIBILITY_VALUE, String.valueOf(visibility));
+        return (db.replace(TABLE_VISIBILITY, VISIBILITY_VALUE, values) != -1);
+    }
+
+    Integer findAccountVisibility(Account account, int uid) {
+        SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+        final Cursor cursor = db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_VALUE},
+                SELECTION_ACCOUNTS_ID_BY_ACCOUNT + " AND " + VISIBILITY_UID + "=? ",
+                new String[] {account.name, account.type, String.valueOf(uid)}, null, null, null);
+        try {
+            while (cursor.moveToNext()) {
+                return cursor.getInt(0);
+            }
+        } finally {
+            cursor.close();
+        }
+        return null;
+    }
+
+    Integer findAccountVisibility(long accountId, int uid) {
+        SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+        final Cursor cursor = db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_VALUE},
+                VISIBILITY_ACCOUNTS_ID + "=? AND " + VISIBILITY_UID + "=? ",
+                new String[] {String.valueOf(accountId), String.valueOf(uid)}, null, null, null);
+        try {
+            while (cursor.moveToNext()) {
+                return cursor.getInt(0);
+            }
+        } finally {
+            cursor.close();
+        }
+        return null;
+    }
+
+    Account findDeAccountByAccountId(long accountId) {
+        SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+        final Cursor cursor = db.query(TABLE_ACCOUNTS, new String[] {ACCOUNTS_NAME, ACCOUNTS_TYPE},
+                ACCOUNTS_ID + "=? ", new String[] {String.valueOf(accountId)}, null, null, null);
+        try {
+            while (cursor.moveToNext()) {
+                return new Account(cursor.getString(0), cursor.getString(1));
+            }
+        } finally {
+            cursor.close();
+        }
+        return null;
+    }
+
+    /**
+     * Returns a map from uid to visibility value.
+     */
+    Map<Integer, Integer> findAccountVisibilityForAccountId(long accountId) {
+        SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+        Map<Integer, Integer> result = new HashMap<>();
+        final Cursor cursor = db.query(TABLE_VISIBILITY,
+                new String[] {VISIBILITY_UID, VISIBILITY_VALUE}, VISIBILITY_ACCOUNTS_ID + "=? ",
+                new String[] {String.valueOf(accountId)}, null, null, null);
+        try {
+            while (cursor.moveToNext()) {
+                result.put(cursor.getInt(0), cursor.getInt(1));
+            }
+        } finally {
+            cursor.close();
+        }
+        return result;
+    }
+
+    boolean deleteAccountVisibilityForUid(int uid) {
+        SQLiteDatabase db = mDeDatabase.getWritableDatabase();
+        return db.delete(TABLE_VISIBILITY, VISIBILITY_UID + "=? ",
+                new String[] {Integer.toString(uid)}) > 0;
+    }
+
     long insertOrReplaceMetaAuthTypeAndUid(String authenticatorType, int uid) {
         SQLiteDatabase db = mDeDatabase.getWritableDatabase();
         ContentValues values = new ContentValues();
@@ -1199,4 +1306,4 @@
         return new AccountsDb(deDatabaseHelper, context, preNDatabaseFile);
     }
 
-}
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1437c83..c8ed872 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1520,7 +1520,7 @@
     static final int PERSIST_URI_GRANTS_MSG = 38;
     static final int REQUEST_ALL_PSS_MSG = 39;
     static final int START_PROFILES_MSG = 40;
-    static final int UPDATE_TIME = 41;
+    static final int UPDATE_TIME_PREFERENCE_MSG = 41;
     static final int SYSTEM_USER_START_MSG = 42;
     static final int SYSTEM_USER_CURRENT_MSG = 43;
     static final int ENTER_ANIMATION_COMPLETE_MSG = 44;
@@ -2026,15 +2026,18 @@
                 }
                 break;
             }
-            case UPDATE_TIME: {
+            case UPDATE_TIME_PREFERENCE_MSG: {
+                // The user's time format preference might have changed.
+                // For convenience we re-use the Intent extra values.
                 synchronized (ActivityManagerService.this) {
-                    for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
+                    for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
                         ProcessRecord r = mLruProcesses.get(i);
                         if (r.thread != null) {
                             try {
-                                r.thread.updateTimePrefs(msg.arg1 == 0 ? false : true);
+                                r.thread.updateTimePrefs(msg.arg1);
                             } catch (RemoteException ex) {
-                                Slog.w(TAG, "Failed to update preferences for: " + r.info.processName);
+                                Slog.w(TAG, "Failed to update preferences for: "
+                                        + r.info.processName);
                             }
                         }
                     }
@@ -8103,7 +8106,12 @@
 
         // Third...  does the caller itself have permission to access
         // this uri?
-        if (UserHandle.getAppId(callingUid) != Process.SYSTEM_UID) {
+        final int callingAppId = UserHandle.getAppId(callingUid);
+        if ((callingAppId == Process.SYSTEM_UID) || (callingAppId == Process.ROOT_UID)) {
+            Slog.w(TAG, "For security reasons, the system cannot issue a Uri permission"
+                    + " grant to " + grantUri + "; use startActivityAsCaller() instead");
+            return -1;
+        } else {
             if (!checkHoldingPermissionsLocked(pm, pi, grantUri, callingUid, modeFlags)) {
                 // Require they hold a strong enough Uri permission
                 if (!checkUriPermissionLocked(grantUri, callingUid, modeFlags)) {
@@ -10338,6 +10346,46 @@
     }
 
     /**
+     * Check if the calling UID has a possible chance at accessing the provider
+     * at the given authority and user.
+     */
+    public String checkContentProviderAccess(String authority, int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            mContext.enforceCallingOrSelfPermission(
+                    Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG);
+            userId = UserHandle.getCallingUserId();
+        }
+
+        ProviderInfo cpi = null;
+        try {
+            cpi = AppGlobals.getPackageManager().resolveContentProvider(authority,
+                    STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS
+                            | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                    userId);
+        } catch (RemoteException ignored) {
+        }
+        if (cpi == null) {
+            // TODO: make this an outright failure in a future platform release;
+            // until then anonymous content notifications are unprotected
+            //return "Failed to find provider " + authority + " for user " + userId;
+            return null;
+        }
+
+        ProcessRecord r = null;
+        synchronized (mPidsSelfLocked) {
+            r = mPidsSelfLocked.get(Binder.getCallingPid());
+        }
+        if (r == null) {
+            return "Failed to find PID " + Binder.getCallingPid();
+        }
+
+        synchronized (this) {
+            return checkContentProviderPermissionLocked(cpi, r, userId, true);
+        }
+    }
+
+    /**
      * Check if {@link ProcessRecord} has a possible chance at accessing the
      * given {@link ProviderInfo}. Final permission checking is always done
      * in {@link ContentProvider}.
@@ -18124,11 +18172,20 @@
                     mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
                     break;
                 case Intent.ACTION_TIME_CHANGED:
-                    // If the user set the time, let all running processes know.
-                    final int is24Hour =
-                            intent.getBooleanExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1
-                                    : 0;
-                    mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
+                    // EXTRA_TIME_PREF_24_HOUR_FORMAT is optional so we must distinguish between
+                    // the tri-state value it may contain and "unknown".
+                    // For convenience we re-use the Intent extra values.
+                    final int NO_EXTRA_VALUE_FOUND = -1;
+                    final int timeFormatPreferenceMsgValue = intent.getIntExtra(
+                            Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT,
+                            NO_EXTRA_VALUE_FOUND /* defaultValue */);
+                    // Only send a message if the time preference is available.
+                    if (timeFormatPreferenceMsgValue != NO_EXTRA_VALUE_FOUND) {
+                        Message updateTimePreferenceMsg =
+                                mHandler.obtainMessage(UPDATE_TIME_PREFERENCE_MSG,
+                                        timeFormatPreferenceMsgValue, 0);
+                        mHandler.sendMessage(updateTimePreferenceMsg);
+                    }
                     BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
                     synchronized (stats) {
                         stats.noteCurrentTimeChangedLocked();
@@ -22070,6 +22127,11 @@
 
     private final class LocalService extends ActivityManagerInternal {
         @Override
+        public String checkContentProviderAccess(String authority, int userId) {
+            return ActivityManagerService.this.checkContentProviderAccess(authority, userId);
+        }
+
+        @Override
         public void onWakefulnessChanged(int wakefulness) {
             ActivityManagerService.this.onWakefulnessChanged(wakefulness);
         }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 1bdef43..473b1a3 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1471,7 +1471,7 @@
             return STACK_INVISIBLE;
         }
 
-        if (mStackSupervisor.isFrontStack(this) || mStackSupervisor.isFocusedStack(this)) {
+        if (mStackSupervisor.isFrontStackOnDisplay(this) || mStackSupervisor.isFocusedStack(this)) {
             return STACK_VISIBLE;
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 539ac16..5d8d79f 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -612,6 +612,15 @@
 
     /** The top most stack. */
     boolean isFrontStack(ActivityStack stack) {
+        return isFrontOfStackList(stack, mHomeStack.mStacks);
+    }
+
+    /** The top most stack on its display. */
+    boolean isFrontStackOnDisplay(ActivityStack stack) {
+        return isFrontOfStackList(stack, stack.mActivityContainer.mActivityDisplay.mStacks);
+    }
+
+    private boolean isFrontOfStackList(ActivityStack stack, List<ActivityStack> stackList) {
         if (stack == null) {
             return false;
         }
@@ -620,7 +629,7 @@
         if (parent != null) {
             stack = parent.getStack();
         }
-        return stack == mHomeStack.mStacks.get((mHomeStack.mStacks.size() - 1));
+        return stack == stackList.get((stackList.size() - 1));
     }
 
     /** NOTE: Should only be called from {@link ActivityStack#moveToFront} */
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index da016da..ac9545c 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -272,7 +272,8 @@
         15, // STREAM_BLUETOOTH_SCO
         7,  // STREAM_SYSTEM_ENFORCED
         15, // STREAM_DTMF
-        15  // STREAM_TTS
+        15, // STREAM_TTS
+        15  // STREAM_ACCESSIBILITY
     };
 
     /** Minimum volume index values for audio streams */
@@ -286,7 +287,8 @@
         0,  // STREAM_BLUETOOTH_SCO
         0,  // STREAM_SYSTEM_ENFORCED
         0,  // STREAM_DTMF
-        0   // STREAM_TTS
+        0,  // STREAM_TTS
+        0   // STREAM_ACCESSIBILITY
     };
 
     /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
@@ -308,7 +310,8 @@
         AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO
         AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED
         AudioSystem.STREAM_RING,            // STREAM_DTMF
-        AudioSystem.STREAM_MUSIC            // STREAM_TTS
+        AudioSystem.STREAM_MUSIC,           // STREAM_TTS
+        AudioSystem.STREAM_MUSIC            // STREAM_ACCESSIBILITY
     };
     private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {
         AudioSystem.STREAM_MUSIC,       // STREAM_VOICE_CALL
@@ -320,7 +323,8 @@
         AudioSystem.STREAM_MUSIC,       // STREAM_BLUETOOTH_SCO
         AudioSystem.STREAM_MUSIC,       // STREAM_SYSTEM_ENFORCED
         AudioSystem.STREAM_MUSIC,       // STREAM_DTMF
-        AudioSystem.STREAM_MUSIC        // STREAM_TTS
+        AudioSystem.STREAM_MUSIC,       // STREAM_TTS
+        AudioSystem.STREAM_MUSIC        // STREAM_ACCESSIBILITY
     };
     private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
         AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL
@@ -332,7 +336,8 @@
         AudioSystem.STREAM_BLUETOOTH_SCO,   // STREAM_BLUETOOTH_SCO
         AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED
         AudioSystem.STREAM_RING,            // STREAM_DTMF
-        AudioSystem.STREAM_MUSIC            // STREAM_TTS
+        AudioSystem.STREAM_MUSIC,           // STREAM_TTS
+        AudioSystem.STREAM_MUSIC            // STREAM_ACCESSIBILITY
     };
     private int[] mStreamVolumeAlias;
 
@@ -351,6 +356,7 @@
         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_SYSTEM_ENFORCED
         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_DTMF
         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_TTS
+        AppOpsManager.OP_AUDIO_ACCESSIBILITY_VOLUME,    // STREAM_ACCESSIBILITY
     };
 
     private final boolean mUseFixedVolume;
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 3b4cef4..886c97f 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -20,11 +20,11 @@
 import android.accounts.Account;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.job.JobInfo;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
-import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IContentService;
@@ -65,7 +65,6 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.security.InvalidParameterException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -295,24 +294,15 @@
 
         final int uid = Binder.getCallingUid();
         final int pid = Binder.getCallingPid();
-        final int callingUserHandle = UserHandle.getCallingUserId();
-        // Registering an observer for any user other than the calling user requires uri grant or
-        // cross user permission
-        if (callingUserHandle != userHandle) {
-            if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle)
-                    != PackageManager.PERMISSION_GRANTED) {
-                enforceCrossUserPermission(userHandle,
-                        "no permission to observe other users' provider view");
-            }
-        }
 
-        if (userHandle < 0) {
-            if (userHandle == UserHandle.USER_CURRENT) {
-                userHandle = ActivityManager.getCurrentUser();
-            } else if (userHandle != UserHandle.USER_ALL) {
-                throw new InvalidParameterException("Bad user handle for registerContentObserver: "
-                        + userHandle);
-            }
+        userHandle = handleIncomingUser(uri, pid, uid,
+                Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle);
+
+        final String msg = LocalServices.getService(ActivityManagerInternal.class)
+                .checkContentProviderAccess(uri.getAuthority(), userHandle);
+        if (msg != null) {
+            Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg);
+            return;
         }
 
         synchronized (mRootNode) {
@@ -362,22 +352,15 @@
         final int uid = Binder.getCallingUid();
         final int pid = Binder.getCallingPid();
         final int callingUserHandle = UserHandle.getCallingUserId();
-        // Notify for any user other than the caller requires uri grant or cross user permission
-        if (callingUserHandle != userHandle) {
-            if (checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
-                    userHandle) != PackageManager.PERMISSION_GRANTED) {
-                enforceCrossUserPermission(userHandle, "no permission to notify other users");
-            }
-        }
 
-        // We passed the permission check; resolve pseudouser targets as appropriate
-        if (userHandle < 0) {
-            if (userHandle == UserHandle.USER_CURRENT) {
-                userHandle = ActivityManager.getCurrentUser();
-            } else if (userHandle != UserHandle.USER_ALL) {
-                throw new InvalidParameterException("Bad user handle for notifyChange: "
-                        + userHandle);
-            }
+        userHandle = handleIncomingUser(uri, pid, uid,
+                Intent.FLAG_GRANT_WRITE_URI_PERMISSION, userHandle);
+
+        final String msg = LocalServices.getService(ActivityManagerInternal.class)
+                .checkContentProviderAccess(uri.getAuthority(), userHandle);
+        if (msg != null) {
+            Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg);
+            return;
         }
 
         // This makes it so that future permission checks will be in the context of this
@@ -1142,6 +1125,27 @@
         }
     }
 
+    private int handleIncomingUser(Uri uri, int pid, int uid, int modeFlags, int userId) {
+        if (userId == UserHandle.USER_CURRENT) {
+            userId = ActivityManager.getCurrentUser();
+        }
+
+        if (userId == UserHandle.USER_ALL) {
+            mContext.enforceCallingOrSelfPermission(
+                    Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG);
+        } else if (userId < 0) {
+            throw new IllegalArgumentException("Invalid user: " + userId);
+        } else if (userId != UserHandle.getCallingUserId()) {
+            if (checkUriPermission(uri, pid, uid, modeFlags,
+                    userId) != PackageManager.PERMISSION_GRANTED) {
+                mContext.enforceCallingOrSelfPermission(
+                        Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG);
+            }
+        }
+
+        return userId;
+    }
+
     /**
      * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL
      * permission, if the userHandle is not for the caller.
diff --git a/services/core/java/com/android/server/pm/EphemeralResolver.java b/services/core/java/com/android/server/pm/EphemeralResolver.java
index 7ddd058..3ce5007 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolver.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolver.java
@@ -46,10 +46,6 @@
 
 /** @hide */
 public abstract class EphemeralResolver {
-
-    /** TODO b/30204367 remove when the platform fully supports ephemeral applications */
-    public static final boolean USE_DEFAULT_EPHEMERAL_LAUNCHER = false;
-
     public static EphemeralResponse doEphemeralResolutionPhaseOne(Context context,
             EphemeralResolverConnection connection, EphemeralRequest requestObj) {
         final Intent intent = requestObj.origIntent;
@@ -162,16 +158,10 @@
                         new IntentSender(failureIntentTarget));
             } catch (RemoteException ignore) { /* ignore; same process */ }
 
-            final Intent ephemeralIntent;
-            if (EphemeralResolver.USE_DEFAULT_EPHEMERAL_LAUNCHER) {
-                // Force the intent to be directed to the ephemeral package
-                ephemeralIntent = new Intent(origIntent);
-                ephemeralIntent.setPackage(ephemeralPackageName);
-            } else {
-                // Success intent goes back to the installer
-                ephemeralIntent = new Intent(launchIntent);
-            }
-
+            // Success intent goes back to the installer
+            final Intent ephemeralIntent = new Intent(launchIntent)
+                    .setComponent(null)
+                    .setPackage(ephemeralPackageName);
             // Intent that is eventually launched if the ephemeral package was
             // installed successfully. This will actually be launched by a platform
             // broadcast receiver.
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index e1b598a..c42647e 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -411,7 +411,7 @@
         }
         if (mService.mInputMethodTarget != null
                 && mService.mInputMethodTarget.mAppToken == mAppToken) {
-            mAppToken.getDisplayContent().moveInputMethodWindowsIfNeeded(true);
+            mAppToken.getDisplayContent().computeImeTarget(true /* updateImeTarget */);
         }
 
         if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + mAppToken
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 5d739d1..4569596 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1006,10 +1006,7 @@
             tStartingWindow.mToken = this;
             tStartingWindow.mAppToken = this;
 
-            if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
-                    "Removing starting window: " + tStartingWindow);
-            getDisplayContent().removeFromWindowList(tStartingWindow);
-            if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
+            if (DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
                     "Removing starting " + tStartingWindow + " from " + fromToken);
             fromToken.removeChild(tStartingWindow);
             fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
@@ -1259,18 +1256,6 @@
         }
     }
 
-    int rebuildWindowListUnchecked(int addIndex) {
-        return super.rebuildWindowList(addIndex);
-    }
-
-    @Override
-    int rebuildWindowList(int addIndex) {
-        if (mIsExiting && !waitingForReplacement()) {
-            return addIndex;
-        }
-        return rebuildWindowListUnchecked(addIndex);
-    }
-
     @Override
     boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
         // For legacy reasons we process the TaskStack.mExitingAppTokens first in DisplayContent
@@ -1332,6 +1317,32 @@
         mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
     }
 
+    WindowState getImeTargetBelowWindow(WindowState w) {
+        final int index = mChildren.indexOf(w);
+        if (index > 0) {
+            final WindowState target = mChildren.get(index - 1);
+            if (target.canBeImeTarget()) {
+                return target;
+            }
+        }
+        return null;
+    }
+
+    WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
+        WindowState candidate = null;
+        for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
+            final WindowState w = mChildren.get(i);
+            if (w.mRemoved) {
+                continue;
+            }
+            if (candidate == null || w.mWinAnimator.mAnimLayer >
+                    candidate.mWinAnimator.mAnimLayer) {
+                candidate = w;
+            }
+        }
+        return candidate;
+    }
+
     @Override
     void dump(PrintWriter pw, String prefix) {
         super.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e73acde..24b9d69 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -33,10 +33,6 @@
 import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.DOCKED_TOP;
-import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
-import static android.view.WindowManager.INPUT_CONSUMER_PIP;
-import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -44,13 +40,10 @@
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -64,7 +57,6 @@
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
@@ -77,10 +69,8 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -94,7 +84,6 @@
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
 import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
 import static com.android.server.wm.WindowManagerService.dipToPixel;
-import static com.android.server.wm.WindowManagerService.localLOGV;
 import static com.android.server.wm.WindowManagerService.logSurface;
 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
@@ -120,29 +109,21 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.DisplayInfo;
-import android.view.IWindow;
-import android.view.InputChannel;
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.WindowManagerPolicy;
 
-import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.ToBooleanFunction;
 import com.android.internal.view.IInputMethodClient;
-import com.android.server.input.InputWindowHandle;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.io.StringWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Function;
 
 /**
  * Utility class for keeping track of the WindowStates and other pertinent contents of a
@@ -174,8 +155,7 @@
     private final NonAppWindowContainers mImeWindowsContainers =
             new NonAppWindowContainers("mImeWindowsContainers");
 
-    // Z-ordered (bottom-most first) list of all Window objects.
-    private final WindowList mWindows = new WindowList();
+    private WindowState mTmpWindow;
 
     // Mapping from a token IBinder to a WindowToken object on this display.
     private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
@@ -232,21 +212,19 @@
 
     final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
 
-    /** Used when rebuilding window list to keep track of windows that have been removed. */
-    private WindowState[] mRebuildTmp = new WindowState[20];
-
-    /**
-     * Temporary list for comparison. Always clear this after use so we don't end up with
-     * orphaned windows references
-     */
-    private final ArrayList<WindowState> mTmpWindows = new ArrayList<>();
+    private boolean mHaveBootMsg = false;
+    private boolean mHaveApp = false;
+    private boolean mHaveWallpaper = false;
+    private boolean mHaveKeyguard = true;
 
     private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
 
     private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
             new TaskForResizePointSearchResult();
-    private final GetWindowOnDisplaySearchResult mTmpGetWindowOnDisplaySearchResult =
-            new GetWindowOnDisplaySearchResult();
+    private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState =
+            new ApplySurfaceChangesTransactionState();
+    private final ScreenshotApplicationState mScreenshotApplicationState =
+            new ScreenshotApplicationState();
 
     // True if this display is in the process of being removed. Used to determine if the removal of
     // the display's direct children should be allowed.
@@ -455,17 +433,13 @@
     @Override
     void onAppTransitionDone() {
         super.onAppTransitionDone();
-        rebuildAppWindowList();
+        mService.mWindowsChanged = true;
     }
 
     @Override
     int getOrientation() {
         final WindowManagerPolicy policy = mService.mPolicy;
 
-        // TODO: All the logic before the last return statement in this method should really go in
-        // #NonAppWindowContainer.getOrientation() since it is trying to decide orientation based
-        // on non-app windows. But, we can not do that until the window list is always correct in
-        // terms of z-ordering based on layers.
         if (mService.mDisplayFrozen) {
             if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
@@ -486,31 +460,9 @@
                 return mService.mLastOrientation;
             }
         } else {
-            for (int pos = mWindows.size() - 1; pos >= 0; --pos) {
-                final WindowState win = mWindows.get(pos);
-                if (win.mAppToken != null) {
-                    // We hit an application window. so the orientation will be determined by the
-                    // app window. No point in continuing further.
-                    break;
-                }
-                if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
-                    continue;
-                }
-                int req = win.mAttrs.screenOrientation;
-                if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND) {
-                    continue;
-                }
-
-                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
-                if (policy.isKeyguardHostWindow(win.mAttrs)) {
-                    mService.mLastKeyguardForcedOrientation = req;
-                }
-                return (mService.mLastWindowForcedOrientation = req);
-            }
-            mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
-
-            if (policy.isKeyguardShowingAndNotOccluded()) {
-                return mService.mLastKeyguardForcedOrientation;
+            final int orientation = mAboveAppWindowsContainers.getOrientation();
+            if (orientation != SCREEN_ORIENTATION_UNSET) {
+                return orientation;
             }
         }
 
@@ -738,22 +690,10 @@
         }
     }
 
+    @Override
     void switchUser() {
-        final int count = mWindows.size();
-        for (int i = 0; i < count; i++) {
-            final WindowState win = mWindows.get(i);
-            if (win.isHiddenFromUserLocked()) {
-                if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win
-                        + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid);
-                win.hideLw(false);
-            }
-        }
-
-        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
-            mTaskStackContainers.get(stackNdx).switchUser();
-        }
-
-        rebuildAppWindowList();
+        super.switchUser();
+        mService.mWindowsChanged = true;
     }
 
     private void resetAnimationBackgroundAnimator() {
@@ -915,19 +855,9 @@
     void setInputMethodAnimLayerAdjustment(int adj) {
         if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj);
         mInputMethodAnimLayerAdjustment = adj;
-        final WindowState imw = mService.mInputMethodWindow;
-        if (imw != null) {
-            imw.adjustAnimLayer(adj);
-        }
-        for (int i = mService.mInputMethodDialogs.size() - 1; i >= 0; i--) {
-            final WindowState dialog = mService.mInputMethodDialogs.get(i);
-            // TODO: This and other places setting mAnimLayer can probably use WS.adjustAnimLayer,
-            // but need to make sure we are not setting things twice for child windows that are
-            // already in the list.
-            dialog.mWinAnimator.mAnimLayer = dialog.mLayer + adj;
-            if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw
-                    + " anim layer: " + dialog.mWinAnimator.mAnimLayer);
-        }
+        mImeWindowsContainers.forAllWindows(w -> {
+            w.adjustAnimLayer(adj);
+        }, true /* traverseTopToBottom */);
     }
 
     /**
@@ -936,11 +866,11 @@
      * suddenly disappear.
      */
     int getLayerForAnimationBackground(WindowStateAnimator winAnimator) {
-        for (int i = mWindows.size() - 1; i >= 0; --i) {
-            final WindowState win = mWindows.get(i);
-            if (win.mIsWallpaper && win.isVisibleNow()) {
-                return win.mWinAnimator.mAnimLayer;
-            }
+        final WindowState visibleWallpaper = mBelowAppWindowsContainers.getWindow(
+                w -> w.mIsWallpaper && w.isVisibleNow());
+
+        if (visibleWallpaper != null) {
+            return visibleWallpaper.mWinAnimator.mAnimLayer;
         }
         return winAnimator.mAnimLayer;
     }
@@ -1088,48 +1018,37 @@
 
     /** Find the visible, touch-deliverable window under the given point */
     WindowState getTouchableWinAtPointLocked(float xf, float yf) {
-        WindowState touchedWin = null;
         final int x = (int) xf;
         final int y = (int) yf;
-
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            WindowState window = mWindows.get(i);
-            final int flags = window.mAttrs.flags;
-            if (!window.isVisibleLw()) {
-                continue;
+        final WindowState touchedWin = getWindow(w -> {
+            final int flags = w.mAttrs.flags;
+            if (!w.isVisibleLw()) {
+                return false;
             }
             if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
-                continue;
+                return false;
             }
 
-            window.getVisibleBounds(mTmpRect);
+            w.getVisibleBounds(mTmpRect);
             if (!mTmpRect.contains(x, y)) {
-                continue;
+                return false;
             }
 
-            window.getTouchableRegion(mTmpRegion);
+            w.getTouchableRegion(mTmpRegion);
 
             final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
-            if (mTmpRegion.contains(x, y) || touchFlags == 0) {
-                touchedWin = window;
-                break;
-            }
-        }
+            return mTmpRegion.contains(x, y) || touchFlags == 0;
+        });
 
         return touchedWin;
     }
 
     boolean canAddToastWindowForUid(int uid) {
         // We allow one toast window per UID being shown at a time.
-        final int windowCount = mWindows.size();
-        for (int i = 0; i < windowCount; i++) {
-            final WindowState window = mWindows.get(i);
-            if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
-                    && !window.mPermanentlyHidden && !window.mWindowRemovalAllowed) {
-                return false;
-            }
-        }
-        return true;
+        final WindowState win = getWindow(w ->
+                w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden
+                && !w.mWindowRemovalAllowed);
+        return win == null;
     }
 
     void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
@@ -1137,268 +1056,76 @@
             return;
         }
         final int lostFocusUid = oldFocus.mOwnerUid;
-        final int windowCount = mWindows.size();
         final Handler handler = mService.mH;
-        for (int i = 0; i < windowCount; i++) {
-            final WindowState window = mWindows.get(i);
-            if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) {
-                if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, window)) {
-                    handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, window),
-                            window.mAttrs.hideTimeoutMilliseconds);
+
+        forAllWindows(w -> {
+            if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) {
+                if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) {
+                    handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w),
+                            w.mAttrs.hideTimeoutMilliseconds);
                 }
             }
-        }
+        }, false /* traverseTopToBottom */);
     }
 
     WindowState findFocusedWindow() {
         final AppWindowToken focusedApp = mService.mFocusedApp;
+        mTmpWindow = null;
 
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            final WindowState win = mWindows.get(i);
+        forAllWindows(w -> {
+            if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w
+                    + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys());
 
-            if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win
-                    + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys());
-
-            if (!win.canReceiveKeys()) {
-                continue;
+            if (!w.canReceiveKeys()) {
+                return false;
             }
 
-            final AppWindowToken wtoken = win.mAppToken;
+            final AppWindowToken wtoken = w.mAppToken;
 
             // If this window's application has been removed, just skip it.
             if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
                 if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
                         + (wtoken.removed ? "removed" : "sendingToBottom"));
-                continue;
+                return false;
             }
 
             if (focusedApp == null) {
                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
-                        + " using new focus @ " + i + " = " + win);
-                return win;
+                        + " using new focus @ " + w);
+                mTmpWindow = w;
+                return true;
             }
 
             if (!focusedApp.windowsAreFocusable()) {
                 // Current focused app windows aren't focusable...
                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
-                        + " focusable using new focus @ " + i + " = " + win);
-                return win;
+                        + " focusable using new focus @ " + w);
+                mTmpWindow = w;
+                return true;
             }
 
             // Descend through all of the app tokens and find the first that either matches
             // win.mAppToken (return win) or mFocusedApp (return null).
-            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
+            if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
                 if (focusedApp.compareTo(wtoken) > 0) {
                     // App stack below focused app stack. No focus for you!!!
                     if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
                             "findFocusedWindow: Reached focused app=" + focusedApp);
-                    return null;
+                    mTmpWindow = null;
+                    return true;
                 }
             }
 
-            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ "
-                    + i + " = " + win);
-            return win;
+            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w);
+            mTmpWindow = w;
+            return true;
+        }, true /* traverseTopToBottom */);
+
+        if (mTmpWindow == null) {
+            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
+            return null;
         }
-
-        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
-        return null;
-    }
-
-    void addAppWindowToWindowList(final WindowState win) {
-        final IWindow client = win.mClient;
-
-        WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken);
-        if (!tokenWindowList.isEmpty()) {
-            addAppWindowExisting(win, tokenWindowList);
-            return;
-        }
-
-        // No windows from this token on this display
-        if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
-                + client.asBinder() + " (token=" + this + ")");
-
-        final WindowToken wToken = win.mToken;
-
-        // Figure out where the window should go, based on the order of applications.
-        mTmpGetWindowOnDisplaySearchResult.reset();
-        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mTaskStackContainers.get(i);
-            stack.getWindowOnDisplayBeforeToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
-            if (mTmpGetWindowOnDisplaySearchResult.reachedToken) {
-                // We have reach the token we are interested in. End search.
-                break;
-            }
-        }
-
-        WindowState pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
-
-        // We now know the index into the apps. If we found an app window above, that gives us the
-        // position; else we need to look some more.
-        if (pos != null) {
-            // Move behind any windows attached to this one.
-            final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
-            if (atoken != null) {
-                tokenWindowList = getTokenWindowsOnDisplay(atoken);
-                final int NC = tokenWindowList.size();
-                if (NC > 0) {
-                    WindowState bottom = tokenWindowList.get(0);
-                    if (bottom.mSubLayer < 0) {
-                        pos = bottom;
-                    }
-                }
-            }
-            addWindowToListBefore(win, pos);
-            return;
-        }
-
-        // Continue looking down until we find the first token that has windows on this display.
-        mTmpGetWindowOnDisplaySearchResult.reset();
-        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
-            final TaskStack stack = mTaskStackContainers.get(i);
-            stack.getWindowOnDisplayAfterToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
-            if (mTmpGetWindowOnDisplaySearchResult.foundWindow != null) {
-                // We have found a window after the token. End search.
-                break;
-            }
-        }
-
-        pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
-
-        if (pos != null) {
-            // Move in front of any windows attached to this one.
-            final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
-            if (atoken != null) {
-                final WindowState top = atoken.getTopWindow();
-                if (top != null && top.mSubLayer >= 0) {
-                    pos = top;
-                }
-            }
-            addWindowToListAfter(win, pos);
-            return;
-        }
-
-        // Just search for the start of this layer.
-        final int myLayer = win.mBaseLayer;
-        int i;
-        for (i = mWindows.size() - 1; i >= 0; --i) {
-            final WindowState w = mWindows.get(i);
-            // Dock divider shares the base layer with application windows, but we want to always
-            // keep it above the application windows. The sharing of the base layer is intended
-            // for window animations, which need to be above the dock divider for the duration
-            // of the animation.
-            if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
-                break;
-            }
-        }
-        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
-                "Based on layer: Adding window " + win + " at " + (i + 1) + " of "
-                + mWindows.size());
-        mWindows.add(i + 1, win);
-        mService.mWindowsChanged = true;
-    }
-
-    /** Adds this non-app window to the window list. */
-    void addNonAppWindowToWindowList(WindowState win) {
-        // Figure out where window should go, based on layer.
-        int i;
-        for (i = mWindows.size() - 1; i >= 0; i--) {
-            final WindowState otherWin = mWindows.get(i);
-            if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) {
-                // Wallpaper wanders through the window list, for example to position itself
-                // directly behind keyguard. Because of this it will break the ordering based on
-                // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
-                // we don't want the new window to appear above them. An example of this is adding
-                // of the docked stack divider. Consider a scenario with the following ordering (top
-                // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
-                // to land below the assist preview, so the dock divider must ignore the wallpaper,
-                // with which it shares the base layer.
-                break;
-            }
-        }
-
-        i++;
-        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
-                "Free window: Adding window " + this + " at " + i + " of " + mWindows.size());
-        mWindows.add(i, win);
-        mService.mWindowsChanged = true;
-    }
-
-    void addToWindowList(WindowState win, int index) {
-        mService.mWindowsChanged = true;
-        mWindows.add(index, win);
-    }
-
-    boolean removeFromWindowList(WindowState win) {
-        mService.mWindowsChanged = true;
-        return mWindows.remove(win);
-    }
-
-    private int removeWindowAndChildrenFromWindowList(WindowState win, int interestingPos) {
-        int wpos = mWindows.indexOf(win);
-        if (wpos < 0) {
-            return interestingPos;
-        }
-
-        if (wpos < interestingPos) interestingPos--;
-        if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + this);
-        mWindows.remove(wpos);
-        mService.mWindowsChanged = true;
-        int childWinCount = win.mChildren.size();
-        while (childWinCount > 0) {
-            childWinCount--;
-            final WindowState cw = win.mChildren.get(childWinCount);
-            int cpos = mWindows.indexOf(cw);
-            if (cpos >= 0) {
-                if (cpos < interestingPos) interestingPos--;
-                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
-                        "Temp removing child at " + cpos + ": " + cw);
-                mWindows.remove(cpos);
-            }
-        }
-        return interestingPos;
-    }
-
-    void addChildWindowToWindowList(WindowState win) {
-        final WindowState parentWindow = win.getParentWindow();
-
-        WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken);
-
-        // Figure out this window's ordering relative to the parent window.
-        final int wCount = windowsOnSameDisplay.size();
-        final int sublayer = win.mSubLayer;
-        int largestSublayer = Integer.MIN_VALUE;
-        WindowState windowWithLargestSublayer = null;
-        int i;
-        for (i = 0; i < wCount; i++) {
-            WindowState w = windowsOnSameDisplay.get(i);
-            final int wSublayer = w.mSubLayer;
-            if (wSublayer >= largestSublayer) {
-                largestSublayer = wSublayer;
-                windowWithLargestSublayer = w;
-            }
-            if (sublayer < 0) {
-                // For negative sublayers, we go below all windows in the same sublayer.
-                if (wSublayer >= sublayer) {
-                    addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w);
-                    break;
-                }
-            } else {
-                // For positive sublayers, we go above all windows in the same sublayer.
-                if (wSublayer > sublayer) {
-                    addWindowToListBefore(win, w);
-                    break;
-                }
-            }
-        }
-        if (i >= wCount) {
-            if (sublayer < 0) {
-                addWindowToListBefore(win, parentWindow);
-            } else {
-                addWindowToListAfter(win,
-                        largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow);
-            }
-        }
+        return mTmpWindow;
     }
 
     /** Updates the layer assignment of windows on this display. */
@@ -1409,136 +1136,9 @@
         }
     }
 
-    void adjustWallpaperWindows() {
-        mWallpaperController.adjustWallpaperWindows(this);
-    }
-
-    /**
-     * Z-orders the display window list so that:
-     * <ul>
-     * <li>Any windows that are currently below the wallpaper window stay below the wallpaper
-     *      window.
-     * <li>Exiting application windows are at the bottom, but above the wallpaper window.
-     * <li>All other application windows are above the exiting application windows and ordered based
-     *      on the ordering of their stacks and tasks on the display.
-     * <li>Non-application windows are at the very top.
-     * </ul>
-     * <p>
-     * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window
-     *       surface layering is done in {@link WindowLayersController}.
-     */
-    void rebuildAppWindowList() {
-        int count = mWindows.size();
-        int i;
-        int lastBelow = -1;
-        int numRemoved = 0;
-
-        if (mRebuildTmp.length < count) {
-            mRebuildTmp = new WindowState[count + 10];
-        }
-
-        // First remove all existing app windows.
-        i = 0;
-        while (i < count) {
-            final WindowState w = mWindows.get(i);
-            if (w.mAppToken != null) {
-                final WindowState win = mWindows.remove(i);
-                win.mRebuilding = true;
-                mRebuildTmp[numRemoved] = win;
-                mService.mWindowsChanged = true;
-                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
-                count--;
-                numRemoved++;
-                continue;
-            } else if (lastBelow == i-1) {
-                if (w.mAttrs.type == TYPE_WALLPAPER) {
-                    lastBelow = i;
-                }
-            }
-            i++;
-        }
-
-        // Keep whatever windows were below the app windows still below, by skipping them.
-        lastBelow++;
-        i = lastBelow;
-
-        // First add all of the exiting app tokens...  these are no longer in the main app list,
-        // but still have windows shown. We put them in the back because now that the animation is
-        // over we no longer will care about them.
-        final int numStacks = mTaskStackContainers.size();
-        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
-            AppTokenList exitingAppTokens = mTaskStackContainers.get(stackNdx).mExitingAppTokens;
-            int NT = exitingAppTokens.size();
-            for (int j = 0; j < NT; j++) {
-                i = exitingAppTokens.get(j).rebuildWindowListUnchecked(i);
-            }
-        }
-
-        // And add in the still active app tokens in Z order.
-        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
-            i = mTaskStackContainers.get(stackNdx).rebuildWindowList(i);
-        }
-
-        i -= lastBelow;
-        if (i != numRemoved) {
-            setLayoutNeeded();
-            Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved
-                    + " windows but added " + i + " rebuildAppWindowListLocked() "
-                    + " callers=" + Debug.getCallers(10));
-            for (i = 0; i < numRemoved; i++) {
-                WindowState ws = mRebuildTmp[i];
-                if (ws.mRebuilding) {
-                    StringWriter sw = new StringWriter();
-                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
-                    ws.dump(pw, "", true);
-                    pw.flush();
-                    Slog.w(TAG_WM, "This window was lost: " + ws);
-                    Slog.w(TAG_WM, sw.toString());
-                    ws.mWinAnimator.destroySurfaceLocked();
-                }
-            }
-            Slog.w(TAG_WM, "Current window hierarchy:");
-            dumpChildrenNames();
-            Slog.w(TAG_WM, "Final window list:");
-            dumpWindows();
-        }
-        Arrays.fill(mRebuildTmp, null);
-    }
-
-    /** Rebuilds the display's window list and does a relayout if something changed. */
-    void rebuildAppWindowsAndLayoutIfNeeded() {
-        mTmpWindows.clear();
-        mTmpWindows.addAll(mWindows);
-
-        rebuildAppWindowList();
-
-        // Set displayContent.mLayoutNeeded if window order changed.
-        final int tmpSize = mTmpWindows.size();
-        final int winSize = mWindows.size();
-        int tmpNdx = 0, winNdx = 0;
-        while (tmpNdx < tmpSize && winNdx < winSize) {
-            // Skip over all exiting windows, they've been moved out of order.
-            WindowState tmp;
-            do {
-                tmp = mTmpWindows.get(tmpNdx++);
-            } while (tmpNdx < tmpSize && tmp.mAppToken != null && tmp.mAppToken.mIsExiting);
-
-            WindowState win;
-            do {
-                win = mWindows.get(winNdx++);
-            } while (winNdx < winSize && win.mAppToken != null && win.mAppToken.mIsExiting);
-
-            if (tmp != win) {
-                // Window order changed.
-                setLayoutNeeded();
-                break;
-            }
-        }
-        if (tmpNdx != winNdx) {
-            // One list was different from the other.
-            setLayoutNeeded();
-        }
-        mTmpWindows.clear();
+    void layoutAndAssignWindowLayersIfNeeded() {
+        mService.mWindowsChanged = true;
+        setLayoutNeeded();
 
         if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
                 false /*updateInputWindows*/)) {
@@ -1550,321 +1150,69 @@
         mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
     }
 
-    void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
-        final InputConsumerImpl navInputConsumer =
-                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_NAVIGATION, mDisplayId);
-        final InputConsumerImpl pipInputConsumer =
-                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_PIP, mDisplayId);
-        final InputConsumerImpl wallpaperInputConsumer =
-                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_WALLPAPER, mDisplayId);
-        boolean addInputConsumerHandle = navInputConsumer != null;
-        boolean addPipInputConsumerHandle = pipInputConsumer != null;
-        boolean addWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
-        final Rect pipTouchableBounds = addPipInputConsumerHandle ? new Rect() : null;
-        boolean disableWallpaperTouchEvents = false;
-
-        for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
-            final WindowState child = mWindows.get(winNdx);
-            final InputChannel inputChannel = child.mInputChannel;
-            final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
-            if (inputChannel == null || inputWindowHandle == null || child.mRemoved
-                    || child.isAdjustedForMinimizedDock()) {
-                // Skip this window because it cannot possibly receive input.
-                continue;
-            }
-
-            if (addPipInputConsumerHandle
-                    && child.getStackId() == PINNED_STACK_ID
-                    && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
-                // Update the bounds of the Pip input consumer to match the Pinned stack
-                child.getStack().getBounds(pipTouchableBounds);
-                pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
-                inputMonitor.addInputWindowHandle(pipInputConsumer.mWindowHandle);
-                addPipInputConsumerHandle = false;
-            }
-
-            if (addInputConsumerHandle
-                    && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
-                inputMonitor.addInputWindowHandle(navInputConsumer.mWindowHandle);
-                addInputConsumerHandle = false;
-            }
-
-            if (addWallpaperInputConsumerHandle) {
-                if (child.mAttrs.type == TYPE_WALLPAPER && child.isVisibleLw()) {
-                    // Add the wallpaper input consumer above the first visible wallpaper.
-                    inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
-                    addWallpaperInputConsumerHandle = false;
-                }
-            }
-
-            final int flags = child.mAttrs.flags;
-            final int privateFlags = child.mAttrs.privateFlags;
-            final int type = child.mAttrs.type;
-
-            final boolean hasFocus = child == inputFocus;
-            final boolean isVisible = child.isVisibleLw();
-            if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
-                disableWallpaperTouchEvents = true;
-            }
-            final boolean hasWallpaper = mWallpaperController.isWallpaperTarget(child)
-                    && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
-                    && !disableWallpaperTouchEvents;
-
-            // If there's a drag in progress and 'child' is a potential drop target,
-            // make sure it's been told about the drag
-            if (inDrag && isVisible && isDefaultDisplay) {
-                mService.mDragState.sendDragStartedIfNeededLw(child);
-            }
-
-            inputMonitor.addInputWindowHandle(
-                    inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper);
-        }
-
-        if (addWallpaperInputConsumerHandle) {
-            // No visible wallpaper found, add the wallpaper input consumer at the end.
-            inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
-        }
-    }
-
     /** Returns true if a leaked surface was destroyed */
     boolean destroyLeakedSurfaces() {
-        boolean leakedSurface = false;
-        final int numWindows = mWindows.size();
-        for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-            final WindowState ws = mWindows.get(winNdx);
-            final WindowStateAnimator wsa = ws.mWinAnimator;
+        // Used to indicate that a surface was leaked.
+        mTmpWindow = null;
+        forAllWindows(w -> {
+            final WindowStateAnimator wsa = w.mWinAnimator;
             if (wsa.mSurfaceController == null) {
-                continue;
+                return;
             }
             if (!mService.mSessions.contains(wsa.mSession)) {
                 Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
-                        + ws + " surface=" + wsa.mSurfaceController
-                        + " token=" + ws.mToken
-                        + " pid=" + ws.mSession.mPid
-                        + " uid=" + ws.mSession.mUid);
+                        + w + " surface=" + wsa.mSurfaceController
+                        + " token=" + w.mToken
+                        + " pid=" + w.mSession.mPid
+                        + " uid=" + w.mSession.mUid);
                 wsa.destroySurface();
-                mService.mForceRemoves.add(ws);
-                leakedSurface = true;
-            } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
+                mService.mForceRemoves.add(w);
+                mTmpWindow = w;
+            } else if (w.mAppToken != null && w.mAppToken.clientHidden) {
                 Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
-                        + ws + " surface=" + wsa.mSurfaceController
-                        + " token=" + ws.mAppToken
-                        + " saved=" + ws.hasSavedSurface());
-                if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
+                        + w + " surface=" + wsa.mSurfaceController
+                        + " token=" + w.mAppToken
+                        + " saved=" + w.hasSavedSurface());
+                if (SHOW_TRANSACTIONS) logSurface(w, "LEAK DESTROY", false);
                 wsa.destroySurface();
-                leakedSurface = true;
+                mTmpWindow = w;
             }
-        }
+        }, false /* traverseTopToBottom */);
 
-        return leakedSurface;
-    }
-
-    /** Return the list of Windows on this display associated with the input token. */
-    WindowList getTokenWindowsOnDisplay(WindowToken token) {
-        final WindowList windowList = new WindowList();
-        final int count = mWindows.size();
-        for (int i = 0; i < count; i++) {
-            final WindowState win = mWindows.get(i);
-            if (win.mToken == token) {
-                windowList.add(win);
-            }
-        }
-        return windowList;
-    }
-
-    private void reAddToWindowList(WindowState win) {
-        win.mToken.addWindow(win);
-        // This is a hack to get all of the child windows added as well at the right position. Child
-        // windows should be rare and this case should be rare, so it shouldn't be that big a deal.
-        int wpos = mWindows.indexOf(win);
-        if (wpos >= 0) {
-            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win);
-            mWindows.remove(wpos);
-            mService.mWindowsChanged = true;
-            win.reAddWindow(wpos);
-        }
-    }
-
-    void moveInputMethodDialogs(int pos) {
-        ArrayList<WindowState> dialogs = mService.mInputMethodDialogs;
-
-        final int N = dialogs.size();
-        if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos);
-        for (int i = 0; i < N; i++) {
-            pos = removeWindowAndChildrenFromWindowList(dialogs.get(i), pos);
-        }
-        if (DEBUG_INPUT_METHOD) {
-            Slog.v(TAG_WM, "Window list w/pos=" + pos);
-            logWindowList(mWindows, "  ");
-        }
-
-        WindowState ime = mService.mInputMethodWindow;
-        if (pos >= 0) {
-            // Skip windows owned by the input method.
-            if (ime != null) {
-                while (pos < mWindows.size()) {
-                    WindowState wp = mWindows.get(pos);
-                    if (wp == ime || wp.getParentWindow() == ime) {
-                        pos++;
-                        continue;
-                    }
-                    break;
-                }
-            }
-            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos);
-            for (int i=0; i<N; i++) {
-                WindowState win = dialogs.get(i);
-                pos = win.reAddWindow(pos);
-            }
-            if (DEBUG_INPUT_METHOD) {
-                Slog.v(TAG_WM, "Final window list:");
-                logWindowList(mWindows, "  ");
-            }
-            return;
-        }
-        for (int i=0; i<N; i++) {
-            WindowState win = dialogs.get(i);
-            reAddToWindowList(win);
-            if (DEBUG_INPUT_METHOD) {
-                Slog.v(TAG_WM, "No IM target, final list:");
-                logWindowList(mWindows, "  ");
-            }
-        }
-    }
-
-    boolean moveInputMethodWindowsIfNeeded(boolean needAssignLayers) {
-        final WindowState imWin = mService.mInputMethodWindow;
-        final int DN = mService.mInputMethodDialogs.size();
-        if (imWin == null && DN == 0) {
-            return false;
-        }
-
-        // TODO(multidisplay): IMEs are only supported on the default display.
-        int imPos = findDesiredInputMethodWindowIndex(true);
-        if (imPos >= 0) {
-            // In this case, the input method windows are to be placed
-            // immediately above the window they are targeting.
-
-            // First check to see if the input method windows are already
-            // located here, and contiguous.
-            final int N = mWindows.size();
-            final WindowState firstImWin = imPos < N ? mWindows.get(imPos) : null;
-
-            // Figure out the actual input method window that should be
-            // at the bottom of their stack.
-            WindowState baseImWin = imWin != null ? imWin : mService.mInputMethodDialogs.get(0);
-            final WindowState cw = baseImWin.getBottomChild();
-            if (cw != null && cw.mSubLayer < 0) {
-                baseImWin = cw;
-            }
-
-            if (firstImWin == baseImWin) {
-                // The windows haven't moved...  but are they still contiguous?
-                // First find the top IM window.
-                int pos = imPos+1;
-                while (pos < N) {
-                    if (!(mWindows.get(pos)).mIsImWindow) {
-                        break;
-                    }
-                    pos++;
-                }
-                pos++;
-                // Now there should be no more input method windows above.
-                while (pos < N) {
-                    if ((mWindows.get(pos)).mIsImWindow) {
-                        break;
-                    }
-                    pos++;
-                }
-                if (pos >= N) {
-                    return false;
-                }
-            }
-
-            if (imWin != null) {
-                if (DEBUG_INPUT_METHOD) {
-                    Slog.v(TAG_WM, "Moving IM from " + imPos);
-                    logWindowList(mWindows, "  ");
-                }
-                imPos = removeWindowAndChildrenFromWindowList(imWin, imPos);
-                if (DEBUG_INPUT_METHOD) {
-                    Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":");
-                    logWindowList(mWindows, "  ");
-                }
-                imWin.reAddWindow(imPos);
-                if (DEBUG_INPUT_METHOD) {
-                    Slog.v(TAG_WM, "List after moving IM to " + imPos + ":");
-                    logWindowList(mWindows, "  ");
-                }
-                if (DN > 0) moveInputMethodDialogs(imPos+1);
-            } else {
-                moveInputMethodDialogs(imPos);
-            }
-
-        } else {
-            // In this case, the input method windows go in a fixed layer,
-            // because they aren't currently associated with a focus window.
-
-            if (imWin != null) {
-                if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos);
-                removeWindowAndChildrenFromWindowList(imWin, 0);
-                reAddToWindowList(imWin);
-                if (DEBUG_INPUT_METHOD) {
-                    Slog.v(TAG_WM, "List with no IM target:");
-                    logWindowList(mWindows, "  ");
-                }
-                if (DN > 0) moveInputMethodDialogs(-1);
-            } else {
-                moveInputMethodDialogs(-1);
-            }
-
-        }
-
-        if (needAssignLayers) {
-            assignWindowLayers(false /* setLayoutNeeded */);
-        }
-
-        return true;
+        return mTmpWindow != null;
     }
 
     /**
-     * Dig through the WindowStates and find the one that the Input Method will target.
-     * @param willMove
-     * @return The index+1 in mWindows of the discovered target.
+     * Determine and return the window that should be the IME target.
+     * @param updateImeTarget If true the system IME target will be updated to match what we found.
+     * @return The window that should be used as the IME target or null if there isn't any.
      */
-    int findDesiredInputMethodWindowIndex(boolean willMove) {
+    WindowState computeImeTarget(boolean updateImeTarget) {
         // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
         // same display. Or even when the current IME/target are not on the same screen as the next
         // IME/target. For now only look for input windows on the main screen.
-        WindowState w = null;
-        int i;
-        for (i = mWindows.size() - 1; i >= 0; --i) {
-            final WindowState win = mWindows.get(i);
+        WindowState target = getWindow(w -> {
+            if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.i(TAG_WM, "Checking window @"
+                    + w + " fl=0x" + Integer.toHexString(w.mAttrs.flags));
+            return w.canBeImeTarget();
+        });
 
-            if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i
-                    + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
-            if (canBeImeTarget(win)) {
-                w = win;
-                //Slog.i(TAG_WM, "Putting input method here!");
 
-                // Yet more tricksyness!  If this window is a "starting" window, we do actually want
-                // to be on top of it, but it is not -really- where input will go.  So if the caller
-                // is not actually looking to move the IME, look down below for a real window to
-                // target...
-                if (!willMove && w.mAttrs.type == TYPE_APPLICATION_STARTING && i > 0) {
-                    final WindowState wb = mWindows.get(i-1);
-                    if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
-                        i--;
-                        w = wb;
-                    }
+        // Yet more tricksyness!  If this window is a "starting" window, we do actually want
+        // to be on top of it, but it is not -really- where input will go. So look down below
+        // for a real window to target...
+        if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) {
+            final AppWindowToken token = target.mAppToken;
+            if (token != null) {
+                final WindowState betterTarget = token.getImeTargetBelowWindow(target);
+                if (betterTarget != null) {
+                    target = betterTarget;
                 }
-                break;
             }
         }
 
-        // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
-
-        if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w);
+        if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
+                "Proposed new IME target: " + target);
 
         // Now, a special case -- if the last target's window is in the process of exiting, and is
         // above the new target, keep on the last target to avoid flicker. Consider for example a
@@ -1872,18 +1220,28 @@
         // until it is completely gone so it doesn't drop behind the dialog or its full-screen
         // scrim.
         final WindowState curTarget = mService.mInputMethodTarget;
-        if (curTarget != null
-                && curTarget.isDisplayedLw()
-                && curTarget.isClosing()
-                && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
+        if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing()
+                && (target == null
+                    || curTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer)) {
             if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
-            return mWindows.indexOf(curTarget) + 1;
+            return curTarget;
         }
 
-        if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target="
-                + w + " willMove=" + willMove);
+        if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target
+                + " updateImeTarget=" + updateImeTarget);
 
-        if (willMove && w != null) {
+        if (target == null) {
+            if (updateImeTarget) {
+                if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
+                        + " to null." + (SHOW_STACK_CRAWLS ? " Callers="
+                        + Debug.getCallers(4) : ""));
+                setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0);
+            }
+
+            return null;
+        }
+
+        if (updateImeTarget) {
             AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
             if (token != null) {
 
@@ -1891,24 +1249,8 @@
                 // to look at all windows below the current target that are in this app, finding the
                 // highest visible one in layering.
                 WindowState highestTarget = null;
-                int highestPos = 0;
                 if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
-                    WindowList curWindows = token.getDisplayContent().mWindows;
-                    int pos = curWindows.indexOf(curTarget);
-                    while (pos >= 0) {
-                        WindowState win = curWindows.get(pos);
-                        if (win.mAppToken != token) {
-                            break;
-                        }
-                        if (!win.mRemoved) {
-                            if (highestTarget == null || win.mWinAnimator.mAnimLayer >
-                                    highestTarget.mWinAnimator.mAnimLayer) {
-                                highestTarget = win;
-                                highestPos = pos;
-                            }
-                        }
-                        pos--;
-                    }
+                    highestTarget = token.getHighestAnimLayerWindow(curTarget);
                 }
 
                 if (highestTarget != null) {
@@ -1916,121 +1258,76 @@
                     if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget
                             + " animating=" + highestTarget.mWinAnimator.isAnimationSet()
                             + " layer=" + highestTarget.mWinAnimator.mAnimLayer
-                            + " new layer=" + w.mWinAnimator.mAnimLayer);
+                            + " new layer=" + target.mWinAnimator.mAnimLayer);
 
                     if (appTransition.isTransitionSet()) {
                         // If we are currently setting up for an animation, hold everything until we
                         // can find out what will happen.
-                        mService.mInputMethodTargetWaitingAnim = true;
-                        mService.mInputMethodTarget = highestTarget;
-                        return highestPos + 1;
+                        setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment);
+                        return highestTarget;
                     } else if (highestTarget.mWinAnimator.isAnimationSet() &&
-                            highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
+                            highestTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer) {
                         // If the window we are currently targeting is involved with an animation,
                         // and it is on top of the next target we will be over, then hold off on
                         // moving until that is done.
-                        mService.mInputMethodTargetWaitingAnim = true;
-                        mService.mInputMethodTarget = highestTarget;
-                        return highestPos + 1;
+                        setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment);
+                        return highestTarget;
                     }
                 }
             }
+
+            if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
+                    + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
+            setInputMethodTarget(target, false, target.mAppToken != null
+                    ? target.mAppToken.mAppAnimator.animLayerAdjustment : 0);
         }
 
-        //Slog.i(TAG_WM, "Placing input method @" + (i+1));
-        if (w != null) {
-            if (willMove) {
-                if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
-                        + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
-                mService.mInputMethodTarget = w;
-                mService.mInputMethodTargetWaitingAnim = false;
-                if (w.mAppToken != null) {
-                    setInputMethodAnimLayerAdjustment(
-                            w.mAppToken.mAppAnimator.animLayerAdjustment);
-                } else {
-                    setInputMethodAnimLayerAdjustment(0);
-                }
-            }
-
-            // If the docked divider is visible, we still need to go through this whole excercise to
-            // find the appropriate input method target (used for animations and dialog
-            // adjustments), but for purposes of Z ordering we simply wish to place it above the
-            // docked divider. Unless it is already above the divider.
-            final WindowState dockedDivider = mDividerControllerLocked.getWindow();
-            if (dockedDivider != null && dockedDivider.isVisibleLw()) {
-                int dividerIndex = mWindows.indexOf(dockedDivider);
-                if (dividerIndex > 0 && dividerIndex > i) {
-                    return dividerIndex + 1;
-                }
-            }
-            return i+1;
-        }
-        if (willMove) {
-            if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
-                    + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
-            mService.mInputMethodTarget = null;
-            setInputMethodAnimLayerAdjustment(0);
-        }
-        return -1;
+        return target;
     }
 
-    private static boolean canBeImeTarget(WindowState w) {
-        final int fl = w.mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
-        final int type = w.mAttrs.type;
-
-        if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
-                && type != TYPE_APPLICATION_STARTING) {
-            return false;
+    private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim, int layerAdj) {
+        if (target == mService.mInputMethodTarget
+                && mService.mInputMethodTargetWaitingAnim == targetWaitingAnim
+                && mInputMethodAnimLayerAdjustment == layerAdj) {
+            return;
         }
 
-        if (DEBUG_INPUT_METHOD) {
-            Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
-            if (!w.isVisibleOrAdding()) {
-                Slog.i(TAG_WM, "  mSurfaceController=" + w.mWinAnimator.mSurfaceController
-                        + " relayoutCalled=" + w.mRelayoutCalled
-                        + " viewVis=" + w.mViewVisibility
-                        + " policyVis=" + w.mPolicyVisibility
-                        + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
-                        + " parentHidden=" + w.isParentWindowHidden()
-                        + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying);
-                if (w.mAppToken != null) {
-                    Slog.i(TAG_WM, "  mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
-                }
+        mService.mInputMethodTarget = target;
+        mService.mInputMethodTargetWaitingAnim = targetWaitingAnim;
+        setInputMethodAnimLayerAdjustment(layerAdj);
+        assignWindowLayers(false /* setLayoutNeeded */);
+    }
+
+    boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) {
+        if (top.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
+            return top.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
+        }
+
+        // Used to indicate we have reached the first window in the range we are interested in.
+        mTmpWindow = null;
+
+        // TODO: Figure-out a more efficient way to do this.
+        final WindowState candidate = getWindow(w -> {
+            if (w == top) {
+                // Reached the first window in the range we are interested in.
+                mTmpWindow = w;
             }
-        }
-        return w.isVisibleOrAdding();
-    }
+            if (mTmpWindow == null) {
+                return false;
+            }
 
-    private void logWindowList(final WindowList windows, String prefix) {
-        int N = windows.size();
-        while (N > 0) {
-            N--;
-            Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N));
-        }
-    }
-
-    boolean getNeedsMenu(WindowState win, WindowManagerPolicy.WindowState bottom) {
-        int index = -1;
-        while (true) {
-            if (win.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
-                return win.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
+            if (w.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
+                return true;
             }
             // If we reached the bottom of the range of windows we are considering,
             // assume no menu is needed.
-            if (win == bottom) {
-                return false;
+            if (w == bottom) {
+                return true;
             }
-            // The current window hasn't specified whether menu key is needed; look behind it.
-            // First, we may need to determine the starting position.
-            if (index < 0) {
-                index = mWindows.indexOf(win);
-            }
-            index--;
-            if (index < 0) {
-                return false;
-            }
-            win = mWindows.get(index);
-        }
+            return false;
+        });
+
+        return candidate != null && candidate.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
     }
 
     void setLayoutNeeded() {
@@ -2047,85 +1344,6 @@
         return mLayoutNeeded;
     }
 
-    private void addAppWindowExisting(WindowState win, WindowList tokenWindowList) {
-
-        // If this application has existing windows, we simply place the new window on top of
-        // them... but keep the starting window on top.
-        if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
-            // Base windows go behind everything else.
-            final WindowState lowestWindow = tokenWindowList.get(0);
-            addWindowToListBefore(win, lowestWindow);
-        } else {
-            final AppWindowToken atoken = win.mAppToken;
-            final int windowListPos = tokenWindowList.size();
-            final WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
-            if (atoken != null && lastWindow == atoken.startingWindow) {
-                addWindowToListBefore(win, lastWindow);
-            } else {
-                int newIdx = findIdxBasedOnAppTokens(win);
-                // There is a window above this one associated with the same apptoken note that the
-                // window could be a floating window that was created later or a window at the top
-                // of the list of windows associated with this token.
-                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
-                        "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
-                                + mWindows.size());
-                mWindows.add(newIdx + 1, win);
-                mService.mWindowsChanged = true;
-            }
-        }
-    }
-
-    /** Places the first input window after the second input window in the window list. */
-    private void addWindowToListAfter(WindowState first, WindowState second) {
-        final int i = mWindows.indexOf(second);
-        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
-                "Adding window " + this + " at " + (i + 1) + " of " + mWindows.size()
-                + " (after " + second + ")");
-        mWindows.add(i + 1, first);
-        mService.mWindowsChanged = true;
-    }
-
-    /** Places the first input window before the second input window in the window list. */
-    private void addWindowToListBefore(WindowState first, WindowState second) {
-        int i = mWindows.indexOf(second);
-        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
-                "Adding window " + this + " at " + i + " of " + mWindows.size()
-                + " (before " + second + ")");
-        if (i < 0) {
-            Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows);
-            i = 0;
-        }
-        mWindows.add(i, first);
-        mService.mWindowsChanged = true;
-    }
-
-    /**
-     * This method finds out the index of a window that has the same app token as win. used for z
-     * ordering the windows in mWindows
-     */
-    private int findIdxBasedOnAppTokens(WindowState win) {
-        for(int j = mWindows.size() - 1; j >= 0; j--) {
-            final WindowState wentry = mWindows.get(j);
-            if(wentry.mAppToken == win.mAppToken) {
-                return j;
-            }
-        }
-        return -1;
-    }
-
-    private void dumpChildrenNames() {
-        StringBuilder output = new StringBuilder();
-        dumpChildrenNames(output, " ");
-        Slog.v(TAG_WM, output.toString());
-    }
-
-    private void dumpWindows() {
-        Slog.v(TAG_WM, " Display #" + mDisplayId);
-        for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
-            Slog.v(TAG_WM, "  #" + winNdx + ": " + mWindows.get(winNdx));
-        }
-    }
-
     void dumpTokens(PrintWriter pw, boolean dumpAll) {
         if (mTokenMap.isEmpty()) {
             return;
@@ -2146,25 +1364,24 @@
     }
 
     void dumpWindowAnimators(PrintWriter pw, String subPrefix) {
-        final int count = mWindows.size();
-        for (int j = 0; j < count; j++) {
-            final WindowStateAnimator wAnim = mWindows.get(j).mWinAnimator;
-            pw.println(subPrefix + "Window #" + j + ": " + wAnim);
-        }
+        final int[] index = new int[1];
+        forAllWindows(w -> {
+            final WindowStateAnimator wAnim = w.mWinAnimator;
+            pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim);
+            index[0] = index[0] + 1;
+        }, false /* traverseTopToBottom */);
     }
 
     void enableSurfaceTrace(FileDescriptor fd) {
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            final WindowState win = mWindows.get(i);
-            win.mWinAnimator.enableSurfaceTrace(fd);
-        }
+        forAllWindows(w -> {
+            w.mWinAnimator.enableSurfaceTrace(fd);
+        }, true /* traverseTopToBottom */);
     }
 
     void disableSurfaceTrace() {
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            final WindowState win = mWindows.get(i);
-            win.mWinAnimator.disableSurfaceTrace();
-        }
+        forAllWindows(w -> {
+            w.mWinAnimator.disableSurfaceTrace();
+        }, true /* traverseTopToBottom */);
     }
 
     /**
@@ -2172,63 +1389,68 @@
      */
     void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) {
         final WindowManagerPolicy policy = mService.mPolicy;
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            final WindowState window = mWindows.get(i);
-            if (window.mAppToken == null && policy.canBeHiddenByKeyguardLw(window)) {
-                window.mWinAnimator.setAnimation(
+        forAllWindows(w -> {
+            if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)) {
+                w.mWinAnimator.setAnimation(
                         policy.createHiddenByKeyguardExit(onWallpaper, goingToShade));
             }
-        }
+        }, true /* traverseTopToBottom */);
     }
 
     boolean checkWaitingForWindows() {
 
-        boolean haveBootMsg = false;
-        boolean haveApp = false;
-        // if the wallpaper service is disabled on the device, we're never going to have
-        // wallpaper, don't bother waiting for it
-        boolean haveWallpaper = false;
-        boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_enableWallpaperService)
-                && !mService.mOnlyCore;
-        boolean haveKeyguard = true;
-        final int count = mWindows.size();
-        for (int i = 0; i < count; i++) {
-            final WindowState w = mWindows.get(i);
+        mHaveBootMsg = false;
+        mHaveApp = false;
+        mHaveWallpaper = false;
+        mHaveKeyguard = true;
+
+        final WindowState visibleWindow = getWindow(w -> {
             if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
                 return true;
             }
             if (w.isDrawnLw()) {
                 if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
-                    haveBootMsg = true;
+                    mHaveBootMsg = true;
                 } else if (w.mAttrs.type == TYPE_APPLICATION
                         || w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
-                    haveApp = true;
+                    mHaveApp = true;
                 } else if (w.mAttrs.type == TYPE_WALLPAPER) {
-                    haveWallpaper = true;
+                    mHaveWallpaper = true;
                 } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
-                    haveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
+                    mHaveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
                 }
             }
+            return false;
+        });
+
+        if (visibleWindow != null) {
+            // We have a visible window.
+            return true;
         }
 
+        // if the wallpaper service is disabled on the device, we're never going to have
+        // wallpaper, don't bother waiting for it
+        boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_enableWallpaperService)
+                && !mService.mOnlyCore;
+
         if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
                 "******** booted=" + mService.mSystemBooted
                 + " msg=" + mService.mShowingBootMessages
-                + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
-                + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
-                + " haveKeyguard=" + haveKeyguard);
+                + " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp
+                + " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled
+                + " haveKeyguard=" + mHaveKeyguard);
 
         // If we are turning on the screen to show the boot message, don't do it until the boot
         // message is actually displayed.
-        if (!mService.mSystemBooted && !haveBootMsg) {
+        if (!mService.mSystemBooted && !mHaveBootMsg) {
             return true;
         }
 
         // If we are turning on the screen after the boot is completed normally, don't do so until
         // we have the application and wallpaper.
-        if (mService.mSystemBooted && ((!haveApp && !haveKeyguard) ||
-                (wallpaperEnabled && !haveWallpaper))) {
+        if (mService.mSystemBooted
+                && ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) {
             return true;
         }
 
@@ -2236,10 +1458,8 @@
     }
 
     void updateWindowsForAnimator(WindowAnimator animator) {
-        final WallpaperController wallpaperController = mWallpaperController;
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            WindowState win = mWindows.get(i);
-            WindowStateAnimator winAnimator = win.mWinAnimator;
+        forAllWindows(w -> {
+            WindowStateAnimator winAnimator = w.mWinAnimator;
             if (winAnimator.hasSurface()) {
                 final boolean wasAnimating = winAnimator.mWasAnimating;
                 final boolean nowAnimating = winAnimator.stepAnimationLocked(animator.mCurrentTime);
@@ -2247,10 +1467,10 @@
                 animator.orAnimating(nowAnimating);
 
                 if (DEBUG_WALLPAPER) Slog.v(TAG,
-                        win + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
+                        w + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
 
                 if (wasAnimating && !winAnimator.mAnimating
-                        && wallpaperController.isWallpaperTarget(win)) {
+                        && mWallpaperController.isWallpaperTarget(w)) {
                     animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                     pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
                     if (DEBUG_LAYOUT_REPEATS) {
@@ -2260,10 +1480,10 @@
                 }
             }
 
-            final AppWindowToken atoken = win.mAppToken;
+            final AppWindowToken atoken = w.mAppToken;
             if (winAnimator.mDrawState == READY_TO_SHOW) {
                 if (atoken == null || atoken.allDrawn) {
-                    if (win.performShowLocked()) {
+                    if (w.performShowLocked()) {
                         pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
                         if (DEBUG_LAYOUT_REPEATS) {
                             mService.mWindowPlacerLocked.debugLayoutRepeats(
@@ -2282,23 +1502,22 @@
                     appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
                 }
             }
-        } // end forall windows
+        }, true /* traverseTopToBottom */);
     }
 
     void updateWallpaperForAnimator(WindowAnimator animator) {
         resetAnimationBackgroundAnimator();
 
-        final WindowList windows = mWindows;
-        WindowState detachedWallpaper = null;
+        // Used to indicate a detached wallpaper.
+        mTmpWindow = null;
 
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState win = windows.get(i);
-            final WindowStateAnimator winAnimator = win.mWinAnimator;
+        forAllWindows(w -> {
+            final WindowStateAnimator winAnimator = w.mWinAnimator;
             if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
-                continue;
+                return;
             }
 
-            final int flags = win.mAttrs.flags;
+            final int flags = w.mAttrs.flags;
 
             // If this window is animating, make a note that we have an animating window and take
             // care of a request to run a detached wallpaper animation.
@@ -2306,11 +1525,11 @@
                 if (winAnimator.mAnimation != null) {
                     if ((flags & FLAG_SHOW_WALLPAPER) != 0
                             && winAnimator.mAnimation.getDetachWallpaper()) {
-                        detachedWallpaper = win;
+                        mTmpWindow = w;
                     }
                     final int color = winAnimator.mAnimation.getBackgroundColor();
                     if (color != 0) {
-                        final TaskStack stack = win.getStack();
+                        final TaskStack stack = w.getStack();
                         if (stack != null) {
                             stack.setAnimationBackground(winAnimator, color);
                         }
@@ -2326,62 +1545,43 @@
                     && appAnimator.animating) {
                 if ((flags & FLAG_SHOW_WALLPAPER) != 0
                         && appAnimator.animation.getDetachWallpaper()) {
-                    detachedWallpaper = win;
+                    mTmpWindow = w;
                 }
 
                 final int color = appAnimator.animation.getBackgroundColor();
                 if (color != 0) {
-                    final TaskStack stack = win.getStack();
+                    final TaskStack stack = w.getStack();
                     if (stack != null) {
                         stack.setAnimationBackground(winAnimator, color);
                     }
                 }
             }
-        } // end forall windows
+        }, true /* traverseTopToBottom */);
 
-        if (animator.mWindowDetachedWallpaper != detachedWallpaper) {
+        if (animator.mWindowDetachedWallpaper != mTmpWindow) {
             if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from "
-                    + animator.mWindowDetachedWallpaper + " to " + detachedWallpaper);
-            animator.mWindowDetachedWallpaper = detachedWallpaper;
+                    + animator.mWindowDetachedWallpaper + " to " + mTmpWindow);
+            animator.mWindowDetachedWallpaper = mTmpWindow;
             animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
         }
     }
 
     void prepareWindowSurfaces() {
-        final int count = mWindows.size();
-        for (int j = 0; j < count; j++) {
-            mWindows.get(j).mWinAnimator.prepareSurfaceLocked(true);
-        }
+        forAllWindows(w -> {
+            w.mWinAnimator.prepareSurfaceLocked(true);
+        }, false /* traverseTopToBottom */);
     }
 
     boolean inputMethodClientHasFocus(IInputMethodClient client) {
-        // The focus for the client is the window immediately below where we would place the input
-        // method window.
-        int idx = findDesiredInputMethodWindowIndex(false);
-        if (idx <= 0) {
-            return false;
-        }
-
-        WindowState imFocus = mWindows.get(idx - 1);
-        if (DEBUG_INPUT_METHOD) {
-            Slog.i(TAG_WM, "Desired input method target: " + imFocus);
-            Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
-            Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
-        }
-
+        final WindowState imFocus = computeImeTarget(false /* updateImeTarget */);
         if (imFocus == null) {
             return false;
         }
 
-        // This may be a starting window, in which case we still want to count it as okay.
-        if (imFocus.mAttrs.type == TYPE_APPLICATION_STARTING && imFocus.mAppToken != null) {
-            // The client has definitely started, so it really should have a window in this app
-            // token. Let's look for it.
-            final WindowState w = imFocus.mAppToken.getFirstNonStartingWindow();
-            if (w != null) {
-                if (DEBUG_INPUT_METHOD) Slog.i(TAG_WM, "Switching to real app window: " + w);
-                imFocus = w;
-            }
+        if (DEBUG_INPUT_METHOD) {
+            Slog.i(TAG_WM, "Desired input method target: " + imFocus);
+            Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
+            Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
         }
 
         final IInputMethodClient imeClient = imFocus.mSession.mClient;
@@ -2398,75 +1598,63 @@
     }
 
     boolean hasSecureWindowOnScreen() {
-        for (int i = mWindows.size() - 1; i >= 0; --i) {
-            final WindowState ws = mWindows.get(i);
-            if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
-                return true;
-            }
-        }
-        return false;
+        final WindowState win = getWindow(
+                w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0);
+        return win != null;
     }
 
     void updateSystemUiVisibility(int visibility, int globalDiff) {
-        for (int i = mWindows.size() - 1; i >= 0; --i) {
-            final WindowState ws = mWindows.get(i);
+        forAllWindows(w -> {
             try {
-                int curValue = ws.mSystemUiVisibility;
-                int diff = (curValue ^ visibility) & globalDiff;
-                int newValue = (curValue & ~diff) | (visibility & diff);
+                final int curValue = w.mSystemUiVisibility;
+                final int diff = (curValue ^ visibility) & globalDiff;
+                final int newValue = (curValue & ~diff) | (visibility & diff);
                 if (newValue != curValue) {
-                    ws.mSeq++;
-                    ws.mSystemUiVisibility = newValue;
+                    w.mSeq++;
+                    w.mSystemUiVisibility = newValue;
                 }
-                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
-                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
+                if (newValue != curValue || w.mAttrs.hasSystemUiListeners) {
+                    w.mClient.dispatchSystemUiVisibilityChanged(w.mSeq,
                             visibility, newValue, diff);
                 }
             } catch (RemoteException e) {
                 // so sorry
             }
-        }
+        }, true /* traverseTopToBottom */);
     }
 
     void onWindowFreezeTimeout() {
         Slog.w(TAG_WM, "Window freeze timeout expired.");
         mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
-        for (int i = mWindows.size() - 1; i >= 0; --i) {
-            final WindowState w = mWindows.get(i);
+
+        forAllWindows(w -> {
             if (!w.mOrientationChanging) {
-                continue;
+                return;
             }
             w.mOrientationChanging = false;
             w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
                     - mService.mDisplayFreezeTime);
             Slog.w(TAG_WM, "Force clearing orientation change: " + w);
-        }
+        }, true /* traverseTopToBottom */);
         mService.mWindowPlacerLocked.performSurfacePlacement();
     }
 
     void waitForAllWindowsDrawn() {
         final WindowManagerPolicy policy = mService.mPolicy;
-        for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
-            final WindowState win = mWindows.get(winNdx);
-            final boolean keyguard = policy.isKeyguardHostWindow(win.mAttrs);
-            if (win.isVisibleLw() && (win.mAppToken != null || keyguard)) {
-                win.mWinAnimator.mDrawState = DRAW_PENDING;
+        forAllWindows(w -> {
+            final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
+            if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
+                w.mWinAnimator.mDrawState = DRAW_PENDING;
                 // Force add to mResizingWindows.
-                win.mLastContentInsets.set(-1, -1, -1, -1);
-                mService.mWaitingForDrawn.add(win);
+                w.mLastContentInsets.set(-1, -1, -1, -1);
+                mService.mWaitingForDrawn.add(w);
             }
-        }
+        }, true /* traverseTopToBottom */);
     }
 
     // TODO: Super crazy long method that should be broken down...
     boolean applySurfaceChangesTransaction(boolean recoveringMemory) {
 
-        boolean focusDisplayed = false;
-        boolean displayHasContent = false;
-        float preferredRefreshRate = 0;
-        int preferredModeId = 0;
-
-
         final int dw = mDisplayInfo.logicalWidth;
         final int dh = mDisplayInfo.logicalHeight;
         final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
@@ -2490,7 +1678,7 @@
             // Remove check for default display when there will be support for multiple wallpaper
             // targets (on different displays).
             if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
-                adjustWallpaperWindows();
+                mWallpaperController.adjustWallpaperWindows(this);
             }
 
             if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
@@ -2517,55 +1705,59 @@
 
             if (isDefaultDisplay) {
                 mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
-                for (int i = mWindows.size() - 1; i >= 0; i--) {
-                    final WindowState w = mWindows.get(i);
+                forAllWindows(w -> {
                     mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
                             mService.mInputMethodTarget);
-                }
+                }, true /* traverseTopToBottom */);
                 pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
                 if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
                         "after finishPostLayoutPolicyLw", pendingLayoutChanges);
             }
         } while (pendingLayoutChanges != 0);
 
-        RootWindowContainer root = mService.mRoot;
-        boolean obscured = false;
-        boolean syswin = false;
+        final RootWindowContainer root = mService.mRoot;
+        mTmpApplySurfaceChangesTransactionState.reset();
         resetDimming();
 
         // Only used if default window
         final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
 
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            final WindowState w = mWindows.get(i);
-            final Task task = w.getTask();
-            final boolean obscuredChanged = w.mObscured != obscured;
+        forAllWindows(w -> {
+            final boolean obscuredChanged = w.mObscured !=
+                    mTmpApplySurfaceChangesTransactionState.obscured;
 
             // Update effect.
-            w.mObscured = obscured;
-            if (!obscured) {
+            w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
+            if (!mTmpApplySurfaceChangesTransactionState.obscured) {
                 final boolean isDisplayed = w.isDisplayedLw();
 
                 if (isDisplayed && w.isObscuringFullscreen(mDisplayInfo)) {
                     // This window completely covers everything behind it, so we want to leave all
                     // of them as undimmed (for performance reasons).
                     root.mObscuringWindow = w;
-                    obscured = true;
+                    mTmpApplySurfaceChangesTransactionState.obscured = true;
                 }
 
-                displayHasContent |= root.handleNotObscuredLocked(w, obscured, syswin);
+                mTmpApplySurfaceChangesTransactionState.displayHasContent |=
+                        root.handleNotObscuredLocked(w,
+                                mTmpApplySurfaceChangesTransactionState.obscured,
+                                mTmpApplySurfaceChangesTransactionState.syswin);
 
                 if (w.mHasSurface && isDisplayed) {
                     final int type = w.mAttrs.type;
                     if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
                             || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
-                        syswin = true;
+                        mTmpApplySurfaceChangesTransactionState.syswin = true;
                     }
-                    if (preferredRefreshRate == 0 && w.mAttrs.preferredRefreshRate != 0) {
-                        preferredRefreshRate = w.mAttrs.preferredRefreshRate;
+                    if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
+                            && w.mAttrs.preferredRefreshRate != 0) {
+                        mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
+                                = w.mAttrs.preferredRefreshRate;
                     }
-                    if (preferredModeId == 0 && w.mAttrs.preferredDisplayModeId != 0) {
-                        preferredModeId = w.mAttrs.preferredDisplayModeId;
+                    if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
+                            && w.mAttrs.preferredDisplayModeId != 0) {
+                        mTmpApplySurfaceChangesTransactionState.preferredModeId
+                                = w.mAttrs.preferredDisplayModeId;
                     }
                 }
             }
@@ -2638,16 +1830,16 @@
 
             if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
                     && w.isDisplayedLw()) {
-                focusDisplayed = true;
+                mTmpApplySurfaceChangesTransactionState.focusDisplayed = true;
             }
 
             w.updateResizingWindowIfNeeded();
-        }
+        }, true /* traverseTopToBottom */);
 
         mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
-                displayHasContent,
-                preferredRefreshRate,
-                preferredModeId,
+                mTmpApplySurfaceChangesTransactionState.displayHasContent,
+                mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
+                mTmpApplySurfaceChangesTransactionState.preferredModeId,
                 true /* inTraversal, must call performTraversalInTrans... below */);
 
         stopDimmingIfNeeded();
@@ -2659,7 +1851,7 @@
             atoken.updateAllDrawn(this);
         }
 
-        return focusDisplayed;
+        return mTmpApplySurfaceChangesTransactionState.focusDisplayed;
     }
 
     void performLayout(boolean initial, boolean updateInputWindows) {
@@ -2692,110 +1884,110 @@
         if (seq < 0) seq = 0;
         mService.mLayoutSeq = seq;
 
-        boolean behindDream = false;
+        // Used to indicate that we have processed the dream window and all additional windows are
+        // behind it.
+        mTmpWindow = null;
 
         // First perform layout of any root windows (not attached to another window).
-        int topAttached = -1;
-        for (i = mWindows.size() - 1; i >= 0; i--) {
-            final WindowState win = mWindows.get(i);
-
+        forAllWindows(w -> {
             // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
             // wasting time and funky changes while a window is animating away.
-            final boolean gone = (behindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win))
-                    || win.isGoneForLayoutLw();
+            final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w))
+                    || w.isGoneForLayoutLw();
 
-            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
-                Slog.v(TAG, "1ST PASS " + win + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
-                        + " mLayoutAttached=" + win.mLayoutAttached
-                        + " screen changed=" + win.isConfigChanged());
-                final AppWindowToken atoken = win.mAppToken;
-                if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + win.mViewVisibility
-                        + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden
+            if (DEBUG_LAYOUT && !w.mLayoutAttached) {
+                Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
+                        + " mLayoutAttached=" + w.mLayoutAttached
+                        + " screen changed=" + w.isConfigChanged());
+                final AppWindowToken atoken = w.mAppToken;
+                if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
+                        + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
                         + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
-                        + " parentHidden=" + win.isParentWindowHidden());
-                else Slog.v(TAG, "  VIS: mViewVisibility=" + win.mViewVisibility
-                        + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden
+                        + " parentHidden=" + w.isParentWindowHidden());
+                else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
+                        + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
                         + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
-                        + " parentHidden=" + win.isParentWindowHidden());
+                        + " parentHidden=" + w.isParentWindowHidden());
             }
 
             // If this view is GONE, then skip it -- keep the current frame, and let the caller know
             // so they can ignore it if they want.  (We do the normal layout for INVISIBLE windows,
             // since that means "perform layout as normal, just don't display").
-            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
-                    || ((win.isConfigChanged() || win.setReportResizeHints())
-                    && !win.isGoneForLayoutLw() &&
-                    ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
-                            (win.mHasSurface && win.mAppToken != null &&
-                                    win.mAppToken.layoutConfigChanges)))) {
-                if (!win.mLayoutAttached) {
+            if (!gone || !w.mHaveFrame || w.mLayoutNeeded
+                    || ((w.isConfigChanged() || w.setReportResizeHints())
+                    && !w.isGoneForLayoutLw() &&
+                    ((w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
+                            (w.mHasSurface && w.mAppToken != null &&
+                                    w.mAppToken.layoutConfigChanges)))) {
+                if (!w.mLayoutAttached) {
                     if (initial) {
                         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
-                        win.mContentChanged = false;
+                        w.mContentChanged = false;
                     }
-                    if (win.mAttrs.type == TYPE_DREAM) {
+                    if (w.mAttrs.type == TYPE_DREAM) {
                         // Don't layout windows behind a dream, so that if it does stuff like hide
                         // the status bar we won't get a bad transition when it goes away.
-                        behindDream = true;
+                        mTmpWindow = w;
                     }
-                    win.mLayoutNeeded = false;
-                    win.prelayout();
-                    mService.mPolicy.layoutWindowLw(win, null);
-                    win.mLayoutSeq = seq;
+                    w.mLayoutNeeded = false;
+                    w.prelayout();
+                    mService.mPolicy.layoutWindowLw(w, null);
+                    w.mLayoutSeq = mService.mLayoutSeq;
 
                     // Window frames may have changed. Update dim layer with the new bounds.
-                    final Task task = win.getTask();
+                    final Task task = w.getTask();
                     if (task != null) {
                         mDimLayerController.updateDimLayer(task);
                     }
 
-                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + win.mFrame
-                            + " mContainingFrame=" + win.mContainingFrame
-                            + " mDisplayFrame=" + win.mDisplayFrame);
-                } else {
-                    if (topAttached < 0) topAttached = i;
+                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.mFrame
+                            + " mContainingFrame=" + w.mContainingFrame
+                            + " mDisplayFrame=" + w.mDisplayFrame);
                 }
             }
-        }
+        }, true /* traverseTopToBottom */);
 
-        boolean attachedBehindDream = false;
+        // Used to indicate that we have processed the dream window and all additional attached
+        // windows are behind it.
+        final WindowState dreamWin = mTmpWindow;
+        mTmpWindow = null;
 
         // Now perform layout of attached windows, which usually depend on the position of the
         // window they are attached to. XXX does not deal with windows that are attached to windows
         // that are themselves attached.
-        for (i = topAttached; i >= 0; i--) {
-            final WindowState win = mWindows.get(i);
-
-            if (win.mLayoutAttached) {
-                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win + " mHaveFrame=" + win.mHaveFrame
-                        + " mViewVisibility=" + win.mViewVisibility
-                        + " mRelayoutCalled=" + win.mRelayoutCalled);
-                // If this view is GONE, then skip it -- keep the current frame, and let the caller
-                // know so they can ignore it if they want.  (We do the normal layout for INVISIBLE
-                // windows, since that means "perform layout as normal, just don't display").
-                if (attachedBehindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win)) {
-                    continue;
+        forAllWindows(w -> {
+            if (w.mLayoutAttached) {
+                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
+                        + " mViewVisibility=" + w.mViewVisibility
+                        + " mRelayoutCalled=" + w.mRelayoutCalled);
+                // If this view is GONE, then skip it -- keep the current frame, and let the
+                // caller know so they can ignore it if they want.  (We do the normal layout for
+                // INVISIBLE windows, since that means "perform layout as normal, just don't
+                // display").
+                if (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) {
+                    return;
                 }
-                if ((win.mViewVisibility != GONE && win.mRelayoutCalled) || !win.mHaveFrame
-                        || win.mLayoutNeeded) {
+                if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
+                        || w.mLayoutNeeded) {
                     if (initial) {
                         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
-                        win.mContentChanged = false;
+                        w.mContentChanged = false;
                     }
-                    win.mLayoutNeeded = false;
-                    win.prelayout();
-                    mService.mPolicy.layoutWindowLw(win, win.getParentWindow());
-                    win.mLayoutSeq = seq;
-                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + win.mFrame
-                            + " mContainingFrame=" + win.mContainingFrame
-                            + " mDisplayFrame=" + win.mDisplayFrame);
+                    w.mLayoutNeeded = false;
+                    w.prelayout();
+                    mService.mPolicy.layoutWindowLw(w, w.getParentWindow());
+                    w.mLayoutSeq = mService.mLayoutSeq;
+                    if (DEBUG_LAYOUT)
+                        Slog.v(TAG, "  LAYOUT: mFrame=" + w.mFrame
+                                + " mContainingFrame=" + w.mContainingFrame
+                                + " mDisplayFrame=" + w.mDisplayFrame);
                 }
-            } else if (win.mAttrs.type == TYPE_DREAM) {
+            } else if (w.mAttrs.type == TYPE_DREAM) {
                 // Don't layout windows behind a dream, so that if it does stuff like hide the
                 // status bar we won't get a bad transition when it goes away.
-                attachedBehindDream = behindDream;
+                mTmpWindow = dreamWin;
             }
-        }
+        }, true /* traverseTopToBottom */);
 
         // Window frames may have changed. Tell the input dispatcher about it.
         mService.mInputMonitor.layoutInputConsumers(dw, dh);
@@ -2819,7 +2011,7 @@
      * @param config of the output bitmap
      * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
      */
-    Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height,
+    Bitmap screenshotApplications(IBinder appToken, int width, int height,
             boolean includeFullDisplay, float frameScale, Bitmap.Config config,
             boolean wallpaperOnly) {
         int dw = mDisplayInfo.logicalWidth;
@@ -2832,22 +2024,10 @@
 
         Bitmap bm = null;
 
-        int maxLayer = 0;
+        mScreenshotApplicationState.reset(appToken == null && !wallpaperOnly);
         final Rect frame = new Rect();
         final Rect stackBounds = new Rect();
 
-        boolean screenshotReady;
-        int minLayer;
-        if (appToken == null && !wallpaperOnly) {
-            screenshotReady = true;
-            minLayer = 0;
-        } else {
-            screenshotReady = false;
-            minLayer = Integer.MAX_VALUE;
-        }
-
-        WindowState appWin = null;
-
         boolean includeImeInScreenshot;
         synchronized(mService.mWindowMap) {
             final AppWindowToken imeTargetAppToken = mService.mInputMethodTarget != null
@@ -2868,70 +2048,69 @@
 
         synchronized(mService.mWindowMap) {
             // Figure out the part of the screen that is actually the app.
-            appWin = null;
-            for (int i = mWindows.size() - 1; i >= 0; i--) {
-                final WindowState ws = mWindows.get(i);
-                if (!ws.mHasSurface) {
-                    continue;
+            mScreenshotApplicationState.appWin = null;
+            forAllWindows(w -> {
+                if (!w.mHasSurface) {
+                    return false;
                 }
-                if (ws.mLayer >= aboveAppLayer) {
-                    continue;
+                if (w.mLayer >= aboveAppLayer) {
+                    return false;
                 }
-                if (wallpaperOnly && !ws.mIsWallpaper) {
-                    continue;
+                if (wallpaperOnly && !w.mIsWallpaper) {
+                    return false;
                 }
-                if (ws.mIsImWindow) {
+                if (w.mIsImWindow) {
                     if (!includeImeInScreenshot) {
-                        continue;
+                        return false;
                     }
-                } else if (ws.mIsWallpaper) {
+                } else if (w.mIsWallpaper) {
                     // If this is the wallpaper layer and we're only looking for the wallpaper layer
                     // then the target window state is this one.
                     if (wallpaperOnly) {
-                        appWin = ws;
+                        mScreenshotApplicationState.appWin = w;
                     }
 
-                    if (appWin == null) {
+                    if (mScreenshotApplicationState.appWin == null) {
                         // We have not ran across the target window yet, so it is probably behind
                         // the wallpaper. This can happen when the keyguard is up and all windows
                         // are moved behind the wallpaper. We don't want to include the wallpaper
                         // layer in the screenshot as it will cover-up the layer of the target
                         // window.
-                        continue;
+                        return false;
                     }
                     // Fall through. The target window is in front of the wallpaper. For this
                     // case we want to include the wallpaper layer in the screenshot because
                     // the target window might have some transparent areas.
                 } else if (appToken != null) {
-                    if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
+                    if (w.mAppToken == null || w.mAppToken.token != appToken) {
                         // This app window is of no interest if it is not associated with the
                         // screenshot app.
-                        continue;
+                        return false;
                     }
-                    appWin = ws;
+                    mScreenshotApplicationState.appWin = w;
                 }
 
                 // Include this window.
 
-                final WindowStateAnimator winAnim = ws.mWinAnimator;
+                final WindowStateAnimator winAnim = w.mWinAnimator;
                 int layer = winAnim.mSurfaceController.getLayer();
-                if (maxLayer < layer) {
-                    maxLayer = layer;
+                if (mScreenshotApplicationState.maxLayer < layer) {
+                    mScreenshotApplicationState.maxLayer = layer;
                 }
-                if (minLayer > layer) {
-                    minLayer = layer;
+                if (mScreenshotApplicationState.minLayer > layer) {
+                    mScreenshotApplicationState.minLayer = layer;
                 }
 
                 // Don't include wallpaper in bounds calculation
-                if (!includeFullDisplay && !ws.mIsWallpaper) {
-                    final Rect wf = ws.mFrame;
-                    final Rect cr = ws.mContentInsets;
+                if (!includeFullDisplay && !w.mIsWallpaper) {
+                    final Rect wf = w.mFrame;
+                    final Rect cr = w.mContentInsets;
                     int left = wf.left + cr.left;
                     int top = wf.top + cr.top;
                     int right = wf.right - cr.right;
                     int bottom = wf.bottom - cr.bottom;
                     frame.union(left, top, right, bottom);
-                    ws.getVisibleBounds(stackBounds);
+                    w.getVisibleBounds(stackBounds);
                     if (!Rect.intersects(frame, stackBounds)) {
                         // Set frame empty if there's no intersection.
                         frame.setEmpty();
@@ -2939,16 +2118,22 @@
                 }
 
                 final boolean foundTargetWs =
-                        (ws.mAppToken != null && ws.mAppToken.token == appToken)
-                                || (appWin != null && wallpaperOnly);
-                if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) {
-                    screenshotReady = true;
+                        (w.mAppToken != null && w.mAppToken.token == appToken)
+                                || (mScreenshotApplicationState.appWin != null && wallpaperOnly);
+                if (foundTargetWs && w.isDisplayedLw() && winAnim.getShown()) {
+                    mScreenshotApplicationState.screenshotReady = true;
                 }
 
-                if (ws.isObscuringFullscreen(mDisplayInfo)){
-                    break;
+                if (w.isObscuringFullscreen(mDisplayInfo)){
+                    return true;
                 }
-            }
+                return false;
+            }, true /* traverseTopToBottom */);
+
+            final WindowState appWin = mScreenshotApplicationState.appWin;
+            final boolean screenshotReady = mScreenshotApplicationState.screenshotReady;
+            final int maxLayer = mScreenshotApplicationState.maxLayer;
+            final int minLayer = mScreenshotApplicationState.minLayer;
 
             if (appToken != null && appWin == null) {
                 // Can't find a window to snapshot.
@@ -3020,14 +2205,13 @@
             if (DEBUG_SCREENSHOT) {
                 Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
                         + maxLayer + " appToken=" + appToken);
-                for (int i = 0; i < mWindows.size(); i++) {
-                    final WindowState win = mWindows.get(i);
-                    final WindowSurfaceController controller = win.mWinAnimator.mSurfaceController;
-                    Slog.i(TAG_WM, win + ": " + win.mLayer
-                            + " animLayer=" + win.mWinAnimator.mAnimLayer
+                forAllWindows(w -> {
+                    final WindowSurfaceController controller = w.mWinAnimator.mSurfaceController;
+                    Slog.i(TAG_WM, w + ": " + w.mLayer
+                            + " animLayer=" + w.mWinAnimator.mAnimLayer
                             + " surfaceLayer=" + ((controller == null)
                             ? "null" : controller.getLayer()));
-                }
+                }, false /* traverseTopToBottom */);
             }
 
             final ScreenRotationAnimation screenRotationAnimation =
@@ -3064,6 +2248,9 @@
                 }
             }
             if (allBlack) {
+                final WindowState appWin = mScreenshotApplicationState.appWin;
+                final int maxLayer = mScreenshotApplicationState.maxLayer;
+                final int minLayer = mScreenshotApplicationState.minLayer;
                 Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
                         Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
                         (appWin != null ?
@@ -3104,32 +2291,23 @@
     }
 
     void onSeamlessRotationTimeout() {
-        boolean layoutNeeded = false;
-        for (int i = mWindows.size() - 1; i >= 0; i--) {
-            final WindowState w = mWindows.get(i);
+        // Used to indicate the layout is needed.
+        mTmpWindow = null;
+
+        forAllWindows(w -> {
             if (!w.mSeamlesslyRotated) {
-                continue;
+                return;
             }
-            layoutNeeded = true;
+            mTmpWindow = w;
             w.setDisplayLayoutNeeded();
             mService.markForSeamlessRotation(w, false);
-        }
+        }, true /* traverseTopToBottom */);
 
-        if (layoutNeeded) {
+        if (mTmpWindow != null) {
             mService.mWindowPlacerLocked.performSurfacePlacement();
         }
     }
 
-    static final class GetWindowOnDisplaySearchResult {
-        boolean reachedToken;
-        WindowState foundWindow;
-
-        void reset() {
-            reachedToken = false;
-            foundWindow = null;
-        }
-    }
-
     static final class TaskForResizePointSearchResult {
         boolean searchDone;
         Task taskForResize;
@@ -3140,6 +2318,39 @@
         }
     }
 
+    private static final class ApplySurfaceChangesTransactionState {
+        boolean displayHasContent;
+        boolean obscured;
+        boolean syswin;
+        boolean focusDisplayed;
+        float preferredRefreshRate;
+        int preferredModeId;
+
+        void reset() {
+            displayHasContent = false;
+            obscured = false;
+            syswin = false;
+            focusDisplayed = false;
+            preferredRefreshRate = 0;
+            preferredModeId = 0;
+        }
+    }
+
+    private static final class ScreenshotApplicationState {
+        WindowState appWin;
+        int maxLayer;
+        int minLayer;
+        boolean screenshotReady;
+
+        void reset(boolean screenshotReady) {
+            appWin = null;
+            maxLayer = 0;
+            minLayer = 0;
+            this.screenshotReady = screenshotReady;
+            minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE;
+        }
+    }
+
     /**
      * Base class for any direct child window container of {@link #DisplayContent} need to inherit
      * from. This is mainly a pass through class that allows {@link #DisplayContent} to have
@@ -3192,15 +2403,6 @@
         void removeStackFromDisplay(TaskStack stack) {
             removeChild(stack);
             stack.onRemovedFromDisplay();
-            // TODO: remove when window list will be gone.
-            // Manually remove records from window list and tap excluded windows list.
-            for (int i = mWindows.size() - 1; i >= 0; --i) {
-                final WindowState windowState = mWindows.get(i);
-                if (stack == windowState.getStack()) {
-                    mWindows.remove(i);
-                    mTapExcludedWindows.remove(windowState);
-                }
-            }
         }
 
         void moveStack(TaskStack stack, boolean toTop) {
@@ -3345,6 +2547,40 @@
         }
 
         @Override
+        int getOrientation() {
+            final WindowManagerPolicy policy = mService.mPolicy;
+            // Find a window requesting orientation.
+            final WindowState win = getWindow((w) -> {
+                if (!w.isVisibleLw() || !w.mPolicyVisibilityAfterAnim) {
+                    return false;
+                }
+                final int req = w.mAttrs.screenOrientation;
+                if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND
+                        || req == SCREEN_ORIENTATION_UNSET) {
+                    return false;
+                }
+                return true;
+            });
+
+            if (win != null) {
+                final int req = win.mAttrs.screenOrientation;
+                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
+                if (policy.isKeyguardHostWindow(win.mAttrs)) {
+                    mService.mLastKeyguardForcedOrientation = req;
+                }
+                return (mService.mLastWindowForcedOrientation = req);
+            }
+
+            mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+
+            if (policy.isKeyguardShowingAndNotOccluded()) {
+                return mService.mLastKeyguardForcedOrientation;
+            }
+
+            return SCREEN_ORIENTATION_UNSET;
+        }
+
+        @Override
         String getName() {
             return mName;
         }
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 12c72e9..01d1c30 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -16,10 +16,15 @@
 
 package com.android.server.wm;
 
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
 import static android.view.WindowManager.INPUT_CONSUMER_PIP;
 import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
@@ -70,6 +75,10 @@
     // Array of window handles to provide to the input dispatcher.
     private InputWindowHandle[] mInputWindowHandles;
     private int mInputWindowHandleCount;
+    private boolean mAddInputConsumerHandle;
+    private boolean mAddPipInputConsumerHandle;
+    private boolean mAddWallpaperInputConsumerHandle;
+    private boolean mDisableWallpaperTouchEvents;
 
     // Set to true when the first input device configuration change notification
     // is received to indicate that the input devices are ready.
@@ -323,12 +332,12 @@
         }
     }
 
-    public void setUpdateInputWindowsNeededLw() {
+    void setUpdateInputWindowsNeededLw() {
         mUpdateInputWindowsNeeded = true;
     }
 
     /* Updates the cached window information provided to the input dispatcher. */
-    public void updateInputWindowsLw(boolean force) {
+    void updateInputWindowsLw(boolean force) {
         if (!force && !mUpdateInputWindowsNeeded) {
             return;
         }
@@ -372,15 +381,92 @@
         }
 
         // Add all windows on the default display.
-        mService.mRoot.updateInputWindows(this, mInputFocus, inDrag);
+        updateInputWindows(inDrag);
+
+        if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
+    }
+
+    private void updateInputWindows(boolean inDrag) {
+
+        clearInputWindowHandlesLw();
+
+        // TODO: multi-display
+        final InputConsumerImpl navInputConsumer =
+                getInputConsumer(INPUT_CONSUMER_NAVIGATION, DEFAULT_DISPLAY);
+        final InputConsumerImpl pipInputConsumer =
+                getInputConsumer(INPUT_CONSUMER_PIP, DEFAULT_DISPLAY);
+        final InputConsumerImpl wallpaperInputConsumer =
+                getInputConsumer(INPUT_CONSUMER_WALLPAPER, DEFAULT_DISPLAY);
+        mAddInputConsumerHandle = navInputConsumer != null;
+        mAddPipInputConsumerHandle = pipInputConsumer != null;
+        mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
+        final Rect pipTouchableBounds = mAddPipInputConsumerHandle ? new Rect() : null;
+        mDisableWallpaperTouchEvents = false;
+
+        final WallpaperController wallpaperController = mService.mRoot.mWallpaperController;
+        mService.mRoot.forAllWindows(w -> {
+            final InputChannel inputChannel = w.mInputChannel;
+            final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
+            if (inputChannel == null || inputWindowHandle == null || w.mRemoved
+                    || w.isAdjustedForMinimizedDock()) {
+                // Skip this window because it cannot possibly receive input.
+                return;
+            }
+
+            if (mAddPipInputConsumerHandle
+                    && w.getStackId() == PINNED_STACK_ID
+                    && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
+                // Update the bounds of the Pip input consumer to match the Pinned stack
+                w.getStack().getBounds(pipTouchableBounds);
+                pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
+                addInputWindowHandle(pipInputConsumer.mWindowHandle);
+                mAddPipInputConsumerHandle = false;
+            }
+
+            if (mAddInputConsumerHandle
+                    && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
+                addInputWindowHandle(navInputConsumer.mWindowHandle);
+                mAddInputConsumerHandle = false;
+            }
+
+            if (mAddWallpaperInputConsumerHandle) {
+                if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) {
+                    // Add the wallpaper input consumer above the first visible wallpaper.
+                    addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
+                    mAddWallpaperInputConsumerHandle = false;
+                }
+            }
+
+            final int flags = w.mAttrs.flags;
+            final int privateFlags = w.mAttrs.privateFlags;
+            final int type = w.mAttrs.type;
+
+            final boolean hasFocus = w == mInputFocus;
+            final boolean isVisible = w.isVisibleLw();
+            if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
+                mDisableWallpaperTouchEvents = true;
+            }
+            final boolean hasWallpaper = wallpaperController.isWallpaperTarget(w)
+                    && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
+                    && !mDisableWallpaperTouchEvents;
+
+            // If there's a drag in progress and 'child' is a potential drop target,
+            // make sure it's been told about the drag
+            if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
+                mService.mDragState.sendDragStartedIfNeededLw(w);
+            }
+
+            addInputWindowHandle(
+                    inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);
+        }, true /* traverseTopToBottom */);
+
+        if (mAddWallpaperInputConsumerHandle) {
+            // No visible wallpaper found, add the wallpaper input consumer at the end.
+            addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
+        }
 
         // Send windows to native code.
         mService.mInputManager.setInputWindows(mInputWindowHandles);
-
-        // Clear the list in preparation for the next round.
-        clearInputWindowHandlesLw();
-
-        if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
     }
 
     /* Notifies that the input device configuration has changed. */
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 88986e3..1962ca7 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -219,7 +219,7 @@
         return false;
     }
 
-    void getWindowsByName(WindowList output, String name) {
+    void getWindowsByName(ArrayList<WindowState> output, String name) {
         int objectId = 0;
         // See if this is an object ID.
         try {
@@ -231,7 +231,7 @@
         getWindowsByName(output, name, objectId);
     }
 
-    private void getWindowsByName(WindowList output, String name, int objectId) {
+    private void getWindowsByName(ArrayList<WindowState> output, String name, int objectId) {
         forAllWindows((w) -> {
             if (name != null) {
                 if (w.mAttrs.getTitle().toString().contains(name)) {
@@ -276,15 +276,6 @@
         return null;
     }
 
-    // TODO: Users would have their own window containers under the display container?
-    void switchUser() {
-        final int count = mChildren.size();
-        for (int i = 0; i < count; ++i) {
-            final DisplayContent dc = mChildren.get(i);
-            dc.switchUser();
-        }
-    }
-
     /**
      * Set new display override config and return array of ids of stacks that were changed during
      * update. If called for the default display, global configuration will also be updated.
@@ -429,14 +420,6 @@
         return hasChanges;
     }
 
-    void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
-        final int count = mChildren.size();
-        for (int i = 0; i < count; ++i) {
-            final DisplayContent dc = mChildren.get(i);
-            dc.updateInputWindows(inputMonitor, inputFocus, inDrag);
-        }
-    }
-
     boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation,
             boolean secure) {
         final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b889db2..772833c8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -589,46 +589,6 @@
         }
     }
 
-    void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
-            DisplayContent.GetWindowOnDisplaySearchResult result) {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final AppWindowToken current = mChildren.get(i);
-            if (current == token) {
-                // We have reach the token we are interested in. End search.
-                result.reachedToken = true;
-                return;
-            }
-
-            // We haven't reached the token yet; if this token is not going to the bottom and
-            // has windows on this display, then it is a candidate for what we are looking for.
-            final WindowList tokenWindowList = dc.getTokenWindowsOnDisplay(current);
-            if (!current.sendingToBottom && tokenWindowList.size() > 0) {
-                result.foundWindow = tokenWindowList.get(0);
-            }
-        }
-    }
-
-    void getWindowOnDisplayAfterToken(DisplayContent dc, WindowToken token,
-            DisplayContent.GetWindowOnDisplaySearchResult result) {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final AppWindowToken current = mChildren.get(i);
-            if (!result.reachedToken) {
-                if (current == token) {
-                    // We have reached the token we are interested in. Get whichever window occurs
-                    // after it that is on the same display.
-                    result.reachedToken = true;
-                }
-                continue;
-            }
-
-            final WindowList tokenWindowList = dc.getTokenWindowsOnDisplay(current);
-            if (tokenWindowList.size() > 0) {
-                result.foundWindow = tokenWindowList.get(tokenWindowList.size() - 1);
-                return;
-            }
-        }
-    }
-
     @Override
     boolean fillsParent() {
         return mFillsParent || !StackId.isTaskResizeAllowed(mStack.mStackId);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 203ba72..f2c74df 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -859,7 +859,9 @@
     }
 
     // TODO: Should each user have there own stacks?
+    @Override
     void switchUser() {
+        super.switchUser();
         int top = mChildren.size();
         for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
             Task task = mChildren.get(taskNdx);
@@ -1488,30 +1490,6 @@
         }
     }
 
-    void getWindowOnDisplayBeforeToken(DisplayContent dc, WindowToken token,
-            DisplayContent.GetWindowOnDisplaySearchResult result) {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final Task task = mChildren.get(i);
-            task.getWindowOnDisplayBeforeToken(dc, token, result);
-            if (result.reachedToken) {
-                // We have reach the token we are interested in. End search.
-                return;
-            }
-        }
-    }
-
-    void getWindowOnDisplayAfterToken(DisplayContent dc, WindowToken token,
-            DisplayContent.GetWindowOnDisplaySearchResult result) {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final Task task = mChildren.get(i);
-            task.getWindowOnDisplayAfterToken(dc, token, result);
-            if (result.foundWindow != null) {
-                // We have found a window after the token. End search.
-                return;
-            }
-        }
-    }
-
     @Override
     int getOrientation() {
         return (StackId.canSpecifyOrientation(mStackId))
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 8dbf2b3..7fd8028 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -683,24 +683,6 @@
         }
     }
 
-    void dumpTokens(PrintWriter pw, String prefix, boolean dumpAll) {
-        if (!mWallpaperTokens.isEmpty()) {
-            pw.println();
-            pw.print(prefix); pw.println("Wallpaper tokens:");
-            for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
-                WindowToken token = mWallpaperTokens.get(i);
-                pw.print(prefix); pw.print("Wallpaper #"); pw.print(i);
-                pw.print(' '); pw.print(token);
-                if (dumpAll) {
-                    pw.println(':');
-                    token.dump(pw, "    ");
-                } else {
-                    pw.println();
-                }
-            }
-        }
-    }
-
     /** Helper class for storing the results of a wallpaper target find operation. */
     final private static class FindWallpaperTargetResult {
         WindowState topWallpaper = null;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index a6a907c..f5db0b6 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -18,7 +18,6 @@
 
 import android.annotation.CallSuper;
 import android.content.res.Configuration;
-import android.view.animation.Animation;
 import com.android.internal.util.ToBooleanFunction;
 
 import java.util.Comparator;
@@ -483,19 +482,11 @@
         return false;
     }
 
-    /**
-     * Rebuilds the WindowList for the input display content.
-     * @param addIndex The index in the window list to add the next entry to.
-     * @return The next index in the window list to.
-     */
-    // TODO: Hoping we can get rid of WindowList so this method wouldn't be needed.
-    int rebuildWindowList(int addIndex) {
-        final int count = mChildren.size();
-        for (int i = 0; i < count; i++) {
-            final WindowContainer wc = mChildren.get(i);
-            addIndex = wc.rebuildWindowList(addIndex);
+    // TODO: Users would have their own window containers under the display container?
+    void switchUser() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            mChildren.get(i).switchUser();
         }
-        return addIndex;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 00d8fba..507679b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -606,17 +606,6 @@
     boolean mInputMethodTargetWaitingAnim;
 
     WindowState mInputMethodWindow = null;
-    // TODO: Remove with extreme prejudice! This list is maintained so that we can keep track of
-    // dialogs that should go on top of the IME so they can be re-arranged in the window list any
-    // time the IME changes position in the window list. Normally you would have a dialog be a child
-    // window of the IME, but they don't share the same token since they are added by different
-    // clients. This doesn't really affect what the user sees on screen since this dialogs have an
-    // higher base layer than the IME window, but it will affect users of the window list that
-    // expect the list to represent the order of things on-screen (e.g input service). This makes
-    // the code for managing the window list hard to follow (see all the places it is used).
-    // We can remove the use of this field when we automatically assign layers and z-order the
-    // window list before it is used whenever window container order changes.
-    final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<>();
 
     boolean mHardKeyboardAvailable;
     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
@@ -1377,19 +1366,16 @@
 
             boolean imMayMove = true;
 
+            win.mToken.addWindow(win);
             if (type == TYPE_INPUT_METHOD) {
                 win.mGivenInsetsPending = true;
                 mInputMethodWindow = win;
-                win.mToken.addImeWindow(win);
+                displayContent.computeImeTarget(true /* updateImeTarget */);
                 imMayMove = false;
             } else if (type == TYPE_INPUT_METHOD_DIALOG) {
-                mInputMethodDialogs.add(win);
-                win.mToken.addWindow(win);
-                displayContent.moveInputMethodDialogs(
-                        displayContent.findDesiredInputMethodWindowIndex(true));
+                displayContent.computeImeTarget(true /* updateImeTarget */);
                 imMayMove = false;
             } else {
-                win.mToken.addWindow(win);
                 if (type == TYPE_WALLPAPER) {
                     displayContent.mWallpaperController.clearLastWallpaperTimeoutTime();
                     displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
@@ -1462,7 +1448,7 @@
             }
 
             if (imMayMove) {
-                displayContent.moveInputMethodWindowsIfNeeded(false);
+                displayContent.computeImeTarget(true /* updateImeTarget */);
             }
 
             // Don't do layout here, the window must call
@@ -1646,8 +1632,6 @@
 
         if (mInputMethodWindow == win) {
             mInputMethodWindow = null;
-        } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
-            mInputMethodDialogs.remove(win);
         }
 
         final WindowToken token = win.mToken;
@@ -1677,13 +1661,11 @@
             dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
         }
 
-        if (dc != null && dc.removeFromWindowList(win)) {
-            if (!mWindowPlacerLocked.isInLayout()) {
-                dc.assignWindowLayers(true /* setLayoutNeeded */);
-                mWindowPlacerLocked.performSurfacePlacement();
-                if (win.mAppToken != null) {
-                    win.mAppToken.updateReportedVisibilityLocked();
-                }
+        if (dc != null && !mWindowPlacerLocked.isInLayout()) {
+            dc.assignWindowLayers(true /* setLayoutNeeded */);
+            mWindowPlacerLocked.performSurfacePlacement();
+            if (win.mAppToken != null) {
+                win.mAppToken.updateReportedVisibilityLocked();
             }
         }
 
@@ -2064,14 +2046,15 @@
             // reassign them at this point if the IM window state gets shuffled
             boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
             final DisplayContent dc = win.getDisplayContent();
-            if (imMayMove && (dc.moveInputMethodWindowsIfNeeded(false) || toBeDisplayed)) {
-                // Little hack here -- we -should- be able to rely on the function to return true if
-                // the IME has moved and needs its layer recomputed.  However, if the IME was hidden
-                // and isn't actually moved in the list, its layer may be out of data so we make
-                // sure to recompute it.
-                // TODO: Probably not needed once the window list always has the right z-ordering
-                // when the window hierarchy is updated.
-                dc.assignWindowLayers(false /* setLayoutNeeded */);
+            if (imMayMove) {
+                dc.computeImeTarget(true /* updateImeTarget */);
+                if (toBeDisplayed) {
+                    // Little hack here -- we -should- be able to rely on the function to return
+                    // true if the IME has moved and needs its layer recomputed. However, if the IME
+                    // was hidden and isn't actually moved in the list, its layer may be out of data
+                    // so we make sure to recompute it.
+                    dc.assignWindowLayers(false /* setLayoutNeeded */);
+                }
             }
 
             if (wallpaperMayMove) {
@@ -3351,7 +3334,7 @@
                 if (mAppTransition.isTransitionSet()) {
                     task.setSendingToBottom(false);
                 }
-                displayContent.rebuildAppWindowsAndLayoutIfNeeded();
+                displayContent.layoutAndAssignWindowLayersIfNeeded();
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -3373,7 +3356,7 @@
                 if (mAppTransition.isTransitionSet()) {
                     task.setSendingToBottom(true);
                 }
-                stack.getDisplayContent().rebuildAppWindowsAndLayoutIfNeeded();
+                stack.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -4619,7 +4602,7 @@
                 return null;
             }
         }
-        return displayContent.screenshotApplications(appToken, displayId, width, height,
+        return displayContent.screenshotApplications(appToken, width, height,
                 includeFullDisplay, frameScale, config, wallpaperOnly);
     }
 
@@ -5181,7 +5164,7 @@
 
         boolean result = true;
 
-        final WindowList windows = new WindowList();
+        final ArrayList<WindowState> windows = new ArrayList();
         synchronized (mWindowMap) {
             mRoot.forAllWindows(w -> {
                 windows.add(w);
@@ -7312,7 +7295,7 @@
         changes |= FINISH_LAYOUT_REDO_LAYOUT;
         if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG_WM,
                 "Wallpaper layer changed: assigning layers + relayout");
-        dc.moveInputMethodWindowsIfNeeded(true);
+        dc.computeImeTarget(true /* updateImeTarget */);
         mRoot.mWallpaperMayChange = true;
         // Since the window list has been rebuilt, focus might have to be recomputed since the
         // actual order of windows might have changed again.
@@ -7405,10 +7388,25 @@
             mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
             // TODO(multidisplay): Focused windows on default display only.
             final DisplayContent displayContent = getDefaultDisplayContentLocked();
-            final boolean imWindowChanged = displayContent.moveInputMethodWindowsIfNeeded(
-                    mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
-                            && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
+            boolean imWindowChanged = false;
+            if (mInputMethodWindow != null) {
+                final WindowState prevTarget = mInputMethodTarget;
+                final WindowState newTarget =
+                        displayContent.computeImeTarget(true /* updateImeTarget*/);
+
+                imWindowChanged = prevTarget != newTarget;
+
+                if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS
+                        && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
+                    final int prevImeAnimLayer = mInputMethodWindow.mWinAnimator.mAnimLayer;
+                    displayContent.assignWindowLayers(false /* setLayoutNeeded */);
+                    imWindowChanged |=
+                            prevImeAnimLayer != mInputMethodWindow.mWinAnimator.mAnimLayer;
+                }
+            }
+
             if (imWindowChanged) {
+                mWindowsChanged = true;
                 displayContent.setLayoutNeeded();
                 newFocus = mRoot.computeFocusedWindow();
             }
@@ -7883,7 +7881,6 @@
     private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
         pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
         mRoot.dumpTokens(pw, dumpAll);
-        mRoot.mWallpaperController.dumpTokens(pw, "  ", dumpAll);
         if (!mFinishedStarting.isEmpty()) {
             pw.println();
             pw.println("  Finishing start of application tokens:");
@@ -7929,16 +7926,6 @@
             ArrayList<WindowState> windows) {
         mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
 
-        if (mInputMethodDialogs.size() > 0) {
-            pw.println();
-            pw.println("  Input method dialogs:");
-            for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
-                WindowState w = mInputMethodDialogs.get(i);
-                if (windows == null || windows.contains(w)) {
-                    pw.print("  IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
-                }
-            }
-        }
         if (mPendingRemove.size() > 0) {
             pw.println();
             pw.println("  Remove pending for:");
@@ -8097,7 +8084,7 @@
 
     private boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti,
             boolean dumpAll) {
-        final WindowList windows = new WindowList();
+        final ArrayList<WindowState> windows = new ArrayList();
         if ("apps".equals(name) || "visible".equals(name) || "visible-apps".equals(name)) {
             final boolean appsOnly = name.contains("apps");
             final boolean visibleOnly = name.contains("visible");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 661df9cd..d959d8c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -76,6 +76,7 @@
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
@@ -115,6 +116,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -140,9 +142,6 @@
 import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
 
-class WindowList extends ArrayList<WindowState> {
-}
-
 /** A window in the window manager. */
 class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState {
     static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM;
@@ -448,12 +447,6 @@
      */
     boolean mWindowRemovalAllowed;
 
-    /**
-     * Temp for keeping track of windows that have been removed when
-     * rebuilding window list.
-     */
-    boolean mRebuilding;
-
     // Input channel and input window handle used by the input dispatcher.
     final InputWindowHandle mInputWindowHandle;
     InputChannel mInputChannel;
@@ -1721,7 +1714,7 @@
 
         final DisplayContent dc = getDisplayContent();
         if (mService.mInputMethodTarget == this) {
-            dc.moveInputMethodWindowsIfNeeded(false);
+            dc.computeImeTarget(true /* updateImeTarget */);
         }
 
         final int type = mAttrs.type;
@@ -1931,6 +1924,33 @@
         return mLayer + specialAdjustment;
     }
 
+    boolean canBeImeTarget() {
+        final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
+        final int type = mAttrs.type;
+
+        if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
+                && type != TYPE_APPLICATION_STARTING) {
+            return false;
+        }
+
+        if (DEBUG_INPUT_METHOD) {
+            Slog.i(TAG_WM, "isVisibleOrAdding " + this + ": " + isVisibleOrAdding());
+            if (!isVisibleOrAdding()) {
+                Slog.i(TAG_WM, "  mSurfaceController=" + mWinAnimator.mSurfaceController
+                        + " relayoutCalled=" + mRelayoutCalled
+                        + " viewVis=" + mViewVisibility
+                        + " policyVis=" + mPolicyVisibility
+                        + " policyVisAfterAnim=" + mPolicyVisibilityAfterAnim
+                        + " parentHidden=" + isParentWindowHidden()
+                        + " exiting=" + mAnimatingExit + " destroying=" + mDestroying);
+                if (mAppToken != null) {
+                    Slog.i(TAG_WM, "  mAppToken.hiddenRequested=" + mAppToken.hiddenRequested);
+                }
+            }
+        }
+        return isVisibleOrAdding();
+    }
+
     void scheduleAnimationIfDimming() {
         final DisplayContent dc = getDisplayContent();
         if (dc == null) {
@@ -2085,7 +2105,7 @@
         return false;
     }
 
-    void removeReplacedWindow() {
+    private void removeReplacedWindow() {
         if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + this);
         if (isDimming()) {
             transferDimToReplacement();
@@ -2138,6 +2158,16 @@
         }
     }
 
+    @Override
+    void switchUser() {
+        super.switchUser();
+        if (isHiddenFromUserLocked()) {
+            if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + this
+                    + ", attrs=" + mAttrs.type + ", belonging to " + mOwnerUid);
+            hideLw(false);
+        }
+    }
+
     int getTouchableRegion(Region region, int flags) {
         final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
         if (modal && mAppToken != null) {
@@ -3499,16 +3529,6 @@
         return mIsChildWindow;
     }
 
-    /**
-     * Returns the bottom child window in regards to z-order of this window or null if no children.
-     */
-    WindowState getBottomChild() {
-        // Child windows are z-ordered based on sub-layer using {@link #sWindowSubLayerComparator}
-        // and the child with the lowest z-order will be at the head of the list.
-        WindowState c = mChildren.peekFirst();
-        return c == null ? null : c;
-    }
-
     boolean layoutInParentFrame() {
         return mIsChildWindow
                 && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
@@ -3795,44 +3815,6 @@
     }
 
     @Override
-    int rebuildWindowList(int addIndex) {
-        return reAddWindow(addIndex);
-    }
-
-    // TODO: come-up with a better name for this method that represents what it does.
-    // Or, it is probably not going to matter anyways if we are successful in getting rid of
-    // the WindowList concept.
-    int reAddWindow(int index) {
-        final DisplayContent dc = getDisplayContent();
-        // Adding child windows relies on child windows being ordered by mSubLayer using
-        // {@link #sWindowSubLayerComparator}.
-        final int childCount = mChildren.size();
-        boolean winAdded = false;
-        for (int j = 0; j < childCount; j++) {
-            final WindowState child = mChildren.get(j);
-            if (!winAdded && child.mSubLayer >= 0) {
-                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
-                        "Re-adding child window at " + index + ": " + child);
-                mRebuilding = false;
-                dc.addToWindowList(this, index);
-                index++;
-                winAdded = true;
-            }
-            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at " + index + ": " + child);
-            child.mRebuilding = false;
-            dc.addToWindowList(child, index);
-            index++;
-        }
-        if (!winAdded) {
-            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Re-adding window at " + index + ": " + this);
-            mRebuilding = false;
-            dc.addToWindowList(this, index);
-            index++;
-        }
-        return index;
-    }
-
-    @Override
     boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
         if (mChildren.isEmpty()) {
             // The window has no children so we just return it.
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 7e1880f..de80837 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -239,7 +239,8 @@
         mService.mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
 
         final DisplayContent displayContent = mService.getDefaultDisplayContentLocked();
-        displayContent.rebuildAppWindowList();
+        // TODO: Don't believe this is really needed...
+        //mService.mWindowsChanged = true;
 
         mService.mRoot.mWallpaperMayChange = false;
 
@@ -356,12 +357,8 @@
         displayContent.setLayoutNeeded();
 
         // TODO(multidisplay): IMEs are only supported on the default display.
-        // TODO: Probably not needed once the window list always has the right z-ordering
-        // when the window hierarchy is updated.
         final DisplayContent dc = mService.getDefaultDisplayContentLocked();
-        if (!dc.moveInputMethodWindowsIfNeeded(true)) {
-            dc.assignWindowLayers(false /*setLayoutNeeded*/);
-        }
+        dc.computeImeTarget(true /* updateImeTarget */);
         mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
                 true /*updateInputWindows*/);
         mService.mFocusMayChange = false;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index a2eebc3..40bd3fb 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -168,13 +168,6 @@
         return highestAnimLayer;
     }
 
-    WindowState getTopWindow() {
-        if (mChildren.isEmpty()) {
-            return null;
-        }
-        return (WindowState) mChildren.get(mChildren.size() - 1).getTop();
-    }
-
     /**
      * Returns true if the new window is considered greater than the existing window in terms of
      * z-order.
@@ -189,51 +182,16 @@
         if (DEBUG_FOCUS) Slog.d(TAG_WM,
                 "addWindow: win=" + win + " Callers=" + Debug.getCallers(5));
 
-        if (!win.isChildWindow()) {
-            if (asAppWindowToken() != null) {
-                mDisplayContent.addAppWindowToWindowList(win);
-            } else {
-                mDisplayContent.addNonAppWindowToWindowList(win);
-            }
-
-            if (!mChildren.contains(win)) {
-                if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
-                addChild(win, mWindowComparator);
-            }
-        } else {
-            mDisplayContent.addChildWindowToWindowList(win);
-        }
-    }
-
-    void addImeWindow(WindowState win) {
-        int pos = mDisplayContent.findDesiredInputMethodWindowIndex(true);
-
-        if (pos < 0) {
-            addWindow(win);
-            mDisplayContent.moveInputMethodDialogs(pos);
+        if (win.isChildWindow()) {
+            // Child windows are added to their parent windows.
             return;
         }
-
-        if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
-                "Adding input method window " + win + " at " + pos);
-        mDisplayContent.addToWindowList(win, pos);
         if (!mChildren.contains(win)) {
-            addChild(win, null);
+            if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
+            addChild(win, mWindowComparator);
+            mService.mWindowsChanged = true;
+            // TODO: Should we also be setting layout needed here and other places?
         }
-        mDisplayContent.moveInputMethodDialogs(pos + 1);
-    }
-
-    /** Return the first window in the token window list that isn't a starting window or null. */
-    WindowState getFirstNonStartingWindow() {
-        final int count = mChildren.size();
-        // We only care about parent windows so no need to loop through child windows.
-        for (int i = 0; i < count; i++) {
-            final WindowState w = mChildren.get(i);
-            if (w.mAttrs.type != TYPE_APPLICATION_STARTING) {
-                return w;
-            }
-        }
-        return null;
     }
 
     /** Returns true if the token windows list is empty. */
diff --git a/services/core/jni/com_android_server_lights_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp
index e6072bb..a3ab8f6 100644
--- a/services/core/jni/com_android_server_lights_LightsService.cpp
+++ b/services/core/jni/com_android_server_lights_LightsService.cpp
@@ -34,6 +34,9 @@
 using Flash      = ::android::hardware::light::V2_0::Flash;
 using Type       = ::android::hardware::light::V2_0::Type;
 using LightState = ::android::hardware::light::V2_0::LightState;
+using Status     = ::android::hardware::light::V2_0::Status;
+template<typename T>
+using Return     = ::android::hardware::Return<T>;
 
 static sp<ILight> gLight;
 
@@ -108,9 +111,33 @@
 
     state.brightnessMode = brightness;
 
+    Status status;
+
     {
         ALOGD_IF_SLOW(50, "Excessive delay setting light");
-        gLight->setLight(type, state);
+        Return<Status> ret = gLight->setLight(type, state);
+
+        // TODO(b/31348667): this is transport specific status
+        if (!ret.getStatus().isOk()) {
+            ALOGE("Failed to issue set light command.");
+            return;
+        }
+
+        status = static_cast<Status>(ret); // hal status
+    }
+
+    switch (status) {
+        case Status::SUCCESS:
+            break;
+        case Status::LIGHT_NOT_SUPPORTED:
+            ALOGE("Light requested not availale on this device.");
+            break;
+        case Status::BRIGHTNESS_NOT_SUPPORTED:
+            ALOGE("Brightness parameter not supported on this device.");
+            break;
+        case Status::UNKNOWN:
+        default:
+            ALOGE("Unknown error setting light.");
     }
 }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ba23f21..1fc4378 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -41,12 +41,10 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.os.storage.IStorageManager;
-import android.provider.Settings;
+import android.util.BootTimingsTraceLog;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
-import android.util.Pair;
 import android.util.Slog;
 import android.view.WindowManager;
 
@@ -55,7 +53,6 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
-import com.android.internal.os.ZygoteInit;
 import com.android.internal.policy.EmergencyAffordanceManager;
 import com.android.internal.widget.ILockSettings;
 import com.android.server.accessibility.AccessibilityManagerService;
@@ -102,8 +99,8 @@
 import com.android.server.storage.DeviceStorageMonitorService;
 import com.android.server.telecom.TelecomLoaderService;
 import com.android.server.trust.TrustManagerService;
-import com.android.server.tv.TvRemoteService;
 import com.android.server.tv.TvInputManagerService;
+import com.android.server.tv.TvRemoteService;
 import com.android.server.twilight.TwilightService;
 import com.android.server.usage.UsageStatsService;
 import com.android.server.vr.VrManagerService;
@@ -112,8 +109,6 @@
 
 import dalvik.system.VMRuntime;
 
-import java.util.ArrayDeque;
-import java.util.Deque;
 import java.io.File;
 import java.io.IOException;
 import java.util.Locale;
@@ -125,11 +120,8 @@
 public final class SystemServer {
     private static final String TAG = "SystemServer";
 
-    private static final boolean LOG_BOOT_TIME = true;
-    // Debug boot time for every step if it's non-user build.
-    private static final boolean DEBUG_BOOT_TIME = LOG_BOOT_TIME && !"user".equals(Build.TYPE);
-    private static final String TAG_BOOT_TIME = "SystemServerTiming";
-    private static final Deque<Pair<String, Long>> START_TIMES = new ArrayDeque<>();
+    private static final BootTimingsTraceLog BOOT_TIMINGS_TRACE_LOG
+            = new BootTimingsTraceLog("SystemServerTiming", Trace.TRACE_TAG_SYSTEM_SERVER);
 
     private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";
     private static final String ENCRYPTED_STATE = "1";
@@ -279,6 +271,11 @@
             int uptimeMillis = (int) SystemClock.uptimeMillis();
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
             MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
+            // Also report when first stage of init has started
+            long initStartNs = SystemProperties.getLong("init.start", -1);
+            if (initStartNs >= 0) {
+                MetricsLogger.histogram(null, "boot_android_init", (int)(initStartNs / 1000000));
+            }
 
             // In case the runtime switched since last boot (such as when
             // the old runtime was removed in an OTA), set the system
@@ -1643,24 +1640,11 @@
     }
 
     private static void traceBeginAndSlog(String name) {
-        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, name);
         Slog.i(TAG, name);
-        if (DEBUG_BOOT_TIME) {
-            START_TIMES.push(Pair.create(name, Long.valueOf(SystemClock.elapsedRealtime())));
-        }
+        BOOT_TIMINGS_TRACE_LOG.traceBegin(name);
     }
 
     private static void traceEnd() {
-        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
-        if (!DEBUG_BOOT_TIME) {
-            return;
-        }
-        Pair<String, Long> event = START_TIMES.pollFirst();
-        if (event == null) {
-            Slog.w(TAG, "traceEnd called more times than traceBeginAndSlog");
-            return;
-        }
-        Slog.d(TAG_BOOT_TIME, event.first + " took to complete: "
-                + (SystemClock.elapsedRealtime() - event.second) + "ms");
+        BOOT_TIMINGS_TRACE_LOG.traceEnd();
     }
 }
diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
index 6b919df..f4c9c86 100644
--- a/services/print/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java
@@ -43,6 +43,7 @@
 import android.util.Slog;
 import android.util.TimedRemoteCaller;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.TransferPipe;
 
 import libcore.io.IoUtils;
@@ -112,6 +113,10 @@
 
     private boolean mCanUnbind;
 
+    /** Whether a thread is currently trying to {@link #bindLocked() bind to the print service} */
+    @GuardedBy("mLock")
+    private boolean mIsBinding;
+
     public static interface PrintSpoolerCallbacks {
         public void onPrintJobQueued(PrintJobInfo printJob);
         public void onAllPrintJobsForServiceHandled(ComponentName printService);
@@ -164,10 +169,8 @@
         try {
             return mGetPrintJobInfosCaller.getPrintJobInfos(getRemoteInstanceLazy(),
                     componentName, state, appId);
-        } catch (RemoteException re) {
-            Slog.e(LOG_TAG, "Error getting print jobs.", re);
-        } catch (TimeoutException te) {
-            Slog.e(LOG_TAG, "Error getting print jobs.", te);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error getting print jobs.", e);
         } finally {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] getPrintJobInfos()");
@@ -188,10 +191,8 @@
         }
         try {
             getRemoteInstanceLazy().createPrintJob(printJob);
-        } catch (RemoteException re) {
-            Slog.e(LOG_TAG, "Error creating print job.", re);
-        } catch (TimeoutException te) {
-            Slog.e(LOG_TAG, "Error creating print job.", te);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error creating print job.", e);
         } finally {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] createPrintJob()");
@@ -211,10 +212,8 @@
         }
         try {
             getRemoteInstanceLazy().writePrintJobData(fd, printJobId);
-        } catch (RemoteException re) {
-            Slog.e(LOG_TAG, "Error writing print job data.", re);
-        } catch (TimeoutException te) {
-            Slog.e(LOG_TAG, "Error writing print job data.", te);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error writing print job data.", e);
         } finally {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] writePrintJobData()");
@@ -238,10 +237,8 @@
         try {
             return mGetPrintJobInfoCaller.getPrintJobInfo(getRemoteInstanceLazy(),
                     printJobId, appId);
-        } catch (RemoteException re) {
-            Slog.e(LOG_TAG, "Error getting print job info.", re);
-        } catch (TimeoutException te) {
-            Slog.e(LOG_TAG, "Error getting print job info.", te);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error getting print job info.", e);
         } finally {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] getPrintJobInfo()");
@@ -263,10 +260,8 @@
         try {
             return mSetPrintJobStatusCaller.setPrintJobState(getRemoteInstanceLazy(),
                     printJobId, state, error);
-        } catch (RemoteException re) {
-            Slog.e(LOG_TAG, "Error setting print job state.", re);
-        } catch (TimeoutException te) {
-            Slog.e(LOG_TAG, "Error setting print job state.", te);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error setting print job state.", e);
         } finally {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobState()");
@@ -294,7 +289,7 @@
         }
         try {
             getRemoteInstanceLazy().setProgress(printJobId, progress);
-        } catch (RemoteException|TimeoutException re) {
+        } catch (RemoteException | TimeoutException | InterruptedException re) {
             Slog.e(LOG_TAG, "Error setting progress.", re);
         } finally {
             if (DEBUG) {
@@ -321,8 +316,8 @@
         }
         try {
             getRemoteInstanceLazy().setStatus(printJobId, status);
-        } catch (RemoteException|TimeoutException re) {
-            Slog.e(LOG_TAG, "Error setting status.", re);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error setting status.", e);
         } finally {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setStatus()");
@@ -350,8 +345,8 @@
         }
         try {
             getRemoteInstanceLazy().setStatusRes(printJobId, status, appPackageName);
-        } catch (RemoteException|TimeoutException re) {
-            Slog.e(LOG_TAG, "Error setting status.", re);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error setting status.", e);
         } finally {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setStatus()");
@@ -380,7 +375,7 @@
         try {
             mCustomPrinterIconLoadedCaller.onCustomPrinterIconLoaded(getRemoteInstanceLazy(),
                     printerId, icon);
-        } catch (RemoteException|TimeoutException re) {
+        } catch (RemoteException | TimeoutException | InterruptedException re) {
             Slog.e(LOG_TAG, "Error loading new custom printer icon.", re);
         } finally {
             if (DEBUG) {
@@ -412,8 +407,8 @@
         try {
             return mGetCustomPrinterIconCaller.getCustomPrinterIcon(getRemoteInstanceLazy(),
                     printerId);
-        } catch (RemoteException|TimeoutException re) {
-            Slog.e(LOG_TAG, "Error getting custom printer icon.", re);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error getting custom printer icon.", e);
             return null;
         } finally {
             if (DEBUG) {
@@ -438,8 +433,8 @@
         }
         try {
             mClearCustomPrinterIconCache.clearCustomPrinterIconCache(getRemoteInstanceLazy());
-        } catch (RemoteException|TimeoutException re) {
-            Slog.e(LOG_TAG, "Error clearing custom printer icon cache.", re);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error clearing custom printer icon cache.", e);
         } finally {
             if (DEBUG) {
                 Slog.i(LOG_TAG,
@@ -462,10 +457,8 @@
         try {
             return mSetPrintJobTagCaller.setPrintJobTag(getRemoteInstanceLazy(),
                     printJobId, tag);
-        } catch (RemoteException re) {
-            Slog.e(LOG_TAG, "Error setting print job tag.", re);
-        } catch (TimeoutException te) {
-            Slog.e(LOG_TAG, "Error setting print job tag.", te);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error setting print job tag.", e);
         } finally {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobTag()");
@@ -487,10 +480,8 @@
         try {
             getRemoteInstanceLazy().setPrintJobCancelling(printJobId,
                     cancelling);
-        } catch (RemoteException re) {
-            Slog.e(LOG_TAG, "Error setting print job cancelling.", re);
-        } catch (TimeoutException te) {
-            Slog.e(LOG_TAG, "Error setting print job cancelling.", te);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error setting print job cancelling.", e);
         } finally {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
@@ -516,8 +507,8 @@
         }
         try {
             getRemoteInstanceLazy().pruneApprovedPrintServices(servicesToKeep);
-        } catch (RemoteException|TimeoutException re) {
-            Slog.e(LOG_TAG, "Error pruning approved print services.", re);
+        } catch (RemoteException | TimeoutException | InterruptedException e) {
+            Slog.e(LOG_TAG, "Error pruning approved print services.", e);
         } finally {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
@@ -538,9 +529,7 @@
         }
         try {
             getRemoteInstanceLazy().removeObsoletePrintJobs();
-        } catch (RemoteException re) {
-            Slog.e(LOG_TAG, "Error removing obsolete print jobs .", re);
-        } catch (TimeoutException te) {
+        } catch (RemoteException | TimeoutException | InterruptedException te) {
             Slog.e(LOG_TAG, "Error removing obsolete print jobs .", te);
         } finally {
             if (DEBUG) {
@@ -578,7 +567,7 @@
             try {
                 TransferPipe.dumpAsync(getRemoteInstanceLazy().asBinder(), fd,
                         new String[] { prefix });
-            } catch (IOException | TimeoutException | RemoteException e) {
+            } catch (IOException | TimeoutException | RemoteException | InterruptedException e) {
                 pw.println("Failed to dump remote instance: " + e);
             }
         }
@@ -595,7 +584,7 @@
         mCallbacks.onPrintJobStateChanged(printJob);
     }
 
-    private IPrintSpooler getRemoteInstanceLazy() throws TimeoutException {
+    private IPrintSpooler getRemoteInstanceLazy() throws TimeoutException, InterruptedException {
         synchronized (mLock) {
             if (mRemoteInstance != null) {
                 return mRemoteInstance;
@@ -605,43 +594,50 @@
         }
     }
 
-    private void bindLocked() throws TimeoutException {
+    private void bindLocked() throws TimeoutException, InterruptedException {
+        while (mIsBinding) {
+            mLock.wait();
+        }
+
         if (mRemoteInstance != null) {
             return;
         }
+
+        mIsBinding = true;
+
         if (DEBUG) {
             Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] bindLocked() " +
                     (mIsLowPriority ? "low priority" : ""));
         }
 
-        int flags;
-        if (mIsLowPriority) {
-            flags = Context.BIND_AUTO_CREATE;
-        } else {
-            flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
-        }
-
-        mContext.bindServiceAsUser(mIntent, mServiceConnection, flags, mUserHandle);
-
-        final long startMillis = SystemClock.uptimeMillis();
-        while (true) {
-            if (mRemoteInstance != null) {
-                break;
+        try {
+            int flags;
+            if (mIsLowPriority) {
+                flags = Context.BIND_AUTO_CREATE;
+            } else {
+                flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
             }
-            final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
-            final long remainingMillis = BIND_SPOOLER_SERVICE_TIMEOUT - elapsedMillis;
-            if (remainingMillis <= 0) {
-                throw new TimeoutException("Cannot get spooler!");
-            }
-            try {
+
+            mContext.bindServiceAsUser(mIntent, mServiceConnection, flags, mUserHandle);
+
+            final long startMillis = SystemClock.uptimeMillis();
+            while (true) {
+                if (mRemoteInstance != null) {
+                    break;
+                }
+                final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
+                final long remainingMillis = BIND_SPOOLER_SERVICE_TIMEOUT - elapsedMillis;
+                if (remainingMillis <= 0) {
+                    throw new TimeoutException("Cannot get spooler!");
+                }
                 mLock.wait(remainingMillis);
-            } catch (InterruptedException ie) {
-                /* ignore */
             }
-        }
 
-        mCanUnbind = true;
-        mLock.notifyAll();
+            mCanUnbind = true;
+        } finally {
+            mIsBinding = false;
+            mLock.notifyAll();
+        }
     }
 
     private void unbindLocked() {
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
index 5b565a7..8591dae 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
@@ -37,6 +37,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -338,4 +339,65 @@
         actualId = mAccountsDb.findDeAccountId(account);
         assertEquals(-1, actualId);
     }
+
+    @Test
+    public void testFindDeAccountByAccountId() {
+        long accId = 10;
+        Account account = new Account("name", "example.com");
+        assertNull(mAccountsDb.findDeAccountByAccountId(accId));
+
+        mAccountsDb.insertDeAccount(account, accId);
+
+        Account foundAccount = mAccountsDb.findDeAccountByAccountId(accId);
+        assertEquals(account, foundAccount);
+    }
+
+    @Test
+    public void testVisibilityFindSetDelete() {
+        long accId = 10;
+        int uid1 = 100500;
+        int uid2 = 100501;
+        Account account = new Account("name", "example.com");
+        assertNull(mAccountsDb.findAccountVisibility(account, uid1));
+
+        mAccountsDb.insertDeAccount(account, accId);
+        assertNull(mAccountsDb.findAccountVisibility(account, uid1));
+        assertNull(mAccountsDb.findAccountVisibility(accId, uid1));
+
+        mAccountsDb.setAccountVisibility(accId, uid1, 1);
+        assertEquals(mAccountsDb.findAccountVisibility(account, uid1), Integer.valueOf(1));
+        assertEquals(mAccountsDb.findAccountVisibility(accId, uid1), Integer.valueOf(1));
+
+        mAccountsDb.setAccountVisibility(accId, uid2, 2);
+        assertEquals(mAccountsDb.findAccountVisibility(accId, uid2), Integer.valueOf(2));
+
+        mAccountsDb.setAccountVisibility(accId, uid2, 3);
+        assertEquals(mAccountsDb.findAccountVisibility(accId, uid2), Integer.valueOf(3));
+
+        Map<Integer, Integer> vis = mAccountsDb.findAccountVisibilityForAccountId(accId);
+        assertEquals(vis.size(), 2);
+        assertEquals(vis.get(uid1), Integer.valueOf(1));
+        assertEquals(vis.get(uid2), Integer.valueOf(3));
+
+        assertTrue(mAccountsDb.deleteAccountVisibilityForUid(uid1));
+        assertNull(mAccountsDb.findAccountVisibility(accId, uid1));
+        assertFalse(mAccountsDb.deleteAccountVisibilityForUid(uid1)); // Already deleted.
+    }
+
+    @Test
+    public void testVisibilityCleanupTrigger() {
+        long accId = 10;
+        int uid1 = 100500;
+        Account account = new Account("name", "example.com");
+
+        assertNull(mAccountsDb.findAccountVisibility(account, uid1));
+        mAccountsDb.insertDeAccount(account, accId);
+        assertNull(mAccountsDb.findAccountVisibility(account, uid1));
+
+        mAccountsDb.setAccountVisibility(accId, uid1, 1);
+        assertEquals(mAccountsDb.findAccountVisibility(accId, uid1), Integer.valueOf(1));
+
+        assertTrue(mAccountsDb.deleteDeAccount(accId)); // Trigger should remove visibility.
+        assertNull(mAccountsDb.findAccountVisibility(account, uid1));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
new file mode 100644
index 0000000..379d4fe
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.pm;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.ArraySet;
+
+import com.android.internal.os.RoSystemProperties;
+import com.android.server.SystemConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.Assert.assertTrue;
+
+
+/**
+ * Presubmit tests for {@link PackageManager}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class PackageManagerPresubmitTest {
+
+    private Context mContext;
+
+    private PackageManager mPackageManager;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getContext();
+        mPackageManager = mContext.getPackageManager();
+    }
+
+    /**
+     * <p>This test ensures that all signature|privileged permissions are granted to core apps like
+     * systemui/settings. If CONTROL_PRIVAPP_PERMISSIONS is set, the test also verifies that
+     * granted permissions are whitelisted in {@link SystemConfig}
+     */
+    @Test
+    @SmallTest
+    @Presubmit
+    public void testPrivAppPermissions() throws PackageManager.NameNotFoundException {
+        String[] testPackages = {"com.android.settings", "com.android.shell",
+                "com.android.systemui"};
+        for (String testPackage : testPackages) {
+            testPackagePrivAppPermission(testPackage);
+        }
+    }
+
+    private void testPackagePrivAppPermission(String testPackage)
+            throws PackageManager.NameNotFoundException {
+        PackageInfo packageInfo = mPackageManager.getPackageInfo(testPackage,
+                PackageManager.GET_PERMISSIONS);
+        ArraySet<String> privAppPermissions = SystemConfig.getInstance()
+                .getPrivAppPermissions(testPackage);
+        for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
+            String pName = packageInfo.requestedPermissions[i];
+            int protectionLevel;
+            boolean platformPermission;
+            try {
+                PermissionInfo permissionInfo = mPackageManager.getPermissionInfo(pName, 0);
+                platformPermission = PackageManagerService.PLATFORM_PACKAGE_NAME.equals(
+                        permissionInfo.packageName);
+                protectionLevel = permissionInfo.protectionLevel;
+            } catch (PackageManager.NameNotFoundException e) {
+                continue;
+            }
+            if ((protectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) {
+                boolean granted = (packageInfo.requestedPermissionsFlags[i]
+                        & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
+                assertTrue("Permission " + pName + " should be granted to " + testPackage, granted);
+                // if CONTROL_PRIVAPP_PERMISSIONS enabled, platform permissions must be whitelisted
+                // in SystemConfig
+                if (platformPermission && RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS) {
+                    assertTrue("Permission " + pName
+                                    + " should be declared in the xml file for package "
+                                    + testPackage,
+                            privAppPermissions.contains(pName));
+                }
+            }
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 50e5a22..3f47d5c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -117,35 +117,6 @@
     }
 
     @Test
-    public void testGetBottomChild() throws Exception {
-        final WindowState parentWindow =
-                createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
-        assertNull(parentWindow.getBottomChild());
-
-        final WindowState child1 =
-                createWindow(parentWindow, TYPE_APPLICATION_PANEL, mWindowToken, "child1");
-        assertEquals(child1, parentWindow.getBottomChild());
-
-        final WindowState child2 =
-                createWindow(parentWindow, TYPE_APPLICATION_PANEL, mWindowToken, "child2");
-        // Since child1 and child2 are at the same layer, then child2 is expect to be added on top
-        // on child1
-        assertEquals(child1, parentWindow.getBottomChild());
-
-        final WindowState child3 =
-                createWindow(parentWindow, TYPE_APPLICATION_MEDIA_OVERLAY, mWindowToken, "child3");
-        // Since child3 is a negative layer, we would expect it to be added below current children
-        // with positive layers.
-        assertEquals(child3, parentWindow.getBottomChild());
-
-        final WindowState child4 =
-                createWindow(parentWindow, TYPE_APPLICATION_MEDIA_OVERLAY, mWindowToken, "child4");
-        // We would also expect additional negative layers to be added below existing negative
-        // layers.
-        assertEquals(child4, parentWindow.getBottomChild());
-    }
-
-    @Test
     public void testGetParentWindow() throws Exception {
         final WindowState parentWindow =
                 createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a79e8ce..457fd88 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -686,42 +686,49 @@
     public static final String EXTRA_DATA_FAILURE_CAUSE = PhoneConstants.DATA_FAILURE_CAUSE_KEY;
 
     /**
-     * Broadcast intent action for letting custom component know to show voicemail notification.
-     * @hide
+     * Broadcast intent action for letting the default dialer to know to show voicemail
+     * notification.
+     *
+     * <p>
+     * The {@link #EXTRA_NOTIFICATION_COUNT} extra indicates the total numbers of unheard
+     * voicemails.
+     * The {@link #EXTRA_VOICEMAIL_NUMBER} extra indicates the voicemail number if available.
+     * The {@link #EXTRA_CALL_VOICEMAIL_INTENT} extra is a {@link android.app.PendingIntent} that
+     * will call the voicemail number when sent. This extra will be empty if the voicemail number
+     * is not set, and {@link #EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT} will be set instead.
+     * The {@link #EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT} extra is a
+     * {@link android.app.PendingIntent} that will launch the voicemail settings. This extra is only
+     * available when the voicemail number is not set.
+     *
+     * @see #EXTRA_NOTIFICATION_COUNT
+     * @see #EXTRA_VOICEMAIL_NUMBER
+     * @see #EXTRA_CALL_VOICEMAIL_INTENT
+     * @see #EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT
      */
-    @SystemApi
     public static final String ACTION_SHOW_VOICEMAIL_NOTIFICATION =
             "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
 
     /**
      * The number of voice messages associated with the notification.
-     * @hide
      */
-    @SystemApi
     public static final String EXTRA_NOTIFICATION_COUNT =
             "android.telephony.extra.NOTIFICATION_COUNT";
 
     /**
      * The voicemail number.
-     * @hide
      */
-    @SystemApi
     public static final String EXTRA_VOICEMAIL_NUMBER =
             "android.telephony.extra.VOICEMAIL_NUMBER";
 
     /**
      * The intent to call voicemail.
-     * @hide
      */
-    @SystemApi
     public static final String EXTRA_CALL_VOICEMAIL_INTENT =
             "android.telephony.extra.CALL_VOICEMAIL_INTENT";
 
     /**
      * The intent to launch voicemail settings.
-     * @hide
      */
-    @SystemApi
     public static final String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT =
             "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
 
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 4a6fb13..34acebf 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -728,10 +728,7 @@
     static private void waitFor(Criteria criteria) {
         int delays = 0;
         while (!criteria.get()) {
-            try {
-                Thread.sleep(50);
-            } catch (InterruptedException e) {
-            }
+            sleepFor(50);
             if (++delays == 10) fail();
         }
     }
@@ -2313,10 +2310,30 @@
         networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
 
         // pass timeout and validate that UNAVAILABLE is not called
-        try {
-            Thread.sleep(15);
-        } catch (InterruptedException e) {
-        }
+        sleepFor(15);
+        networkCallback.assertNoCallback();
+    }
+
+    /**
+     * Validate that a satisfied network request followed by a disconnected (lost) network does
+     * not trigger onUnavailable() once the time-out period expires.
+     */
+    @SmallTest
+    public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
+        NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
+                NetworkCapabilities.TRANSPORT_WIFI).build();
+        final TestNetworkCallback networkCallback = new TestNetworkCallback();
+        mCm.requestNetwork(nr, networkCallback, 500);
+
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connect(false);
+        networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        sleepFor(20);
+        mWiFiNetworkAgent.disconnect();
+        networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+        // pass timeout and validate that UNAVAILABLE is not called
+        sleepFor(600);
         networkCallback.assertNoCallback();
     }
 
@@ -2358,10 +2375,7 @@
         // pass timeout and validate that no callbacks
         // Note: doesn't validate that nothing called from CS since even if called the CM already
         // unregisters the callback and won't pass it through!
-        try {
-            Thread.sleep(15);
-        } catch (InterruptedException e) {
-        }
+        sleepFor(15);
         networkCallback.assertNoCallback();
 
         // create a network satisfying request - validate that request not triggered
@@ -2775,4 +2789,13 @@
             mCm.unregisterNetworkCallback(pendingIntent);
         }
     }
+
+    /* test utilities */
+    static private void sleepFor(int ms) {
+        try {
+            Thread.sleep(ms);
+        } catch (InterruptedException e) {
+        }
+
+    }
 }
diff --git a/wifi/java/android/net/wifi/aware/PublishConfig.java b/wifi/java/android/net/wifi/aware/PublishConfig.java
index 5d3ad058..ba493a0 100644
--- a/wifi/java/android/net/wifi/aware/PublishConfig.java
+++ b/wifi/java/android/net/wifi/aware/PublishConfig.java
@@ -32,9 +32,8 @@
 /**
  * Defines the configuration of a Aware publish session. Built using
  * {@link PublishConfig.Builder}. A publish session is created using
- * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
- * WifiAwareDiscoverySessionCallback)}
- * or updated using
+ * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)} or updated using
  * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)}.
  *
  * @hide PROPOSED_AWARE_API
diff --git a/wifi/java/android/net/wifi/aware/SubscribeConfig.java b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
index 2a6cc93..5e14f8f 100644
--- a/wifi/java/android/net/wifi/aware/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/aware/SubscribeConfig.java
@@ -32,9 +32,8 @@
 /**
  * Defines the configuration of a Aware subscribe session. Built using
  * {@link SubscribeConfig.Builder}. Subscribe is done using
- * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
- * WifiAwareDiscoverySessionCallback)}
- * or
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)} or
  * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
  *
  * @hide PROPOSED_AWARE_API
@@ -403,8 +402,8 @@
          * Sets the match style of the subscription - how are matches from a
          * single match session (corresponding to the same publish action on the
          * peer) reported to the host (using the
-         * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
-         * ). The options are: only report the first match and ignore the rest
+         * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+         * byte[], byte[])}). The options are: only report the first match and ignore the rest
          * {@link SubscribeConfig#MATCH_STYLE_FIRST_ONLY} or report every single
          * match {@link SubscribeConfig#MATCH_STYLE_ALL} (the default).
          *
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java b/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
index 2cace61..1e8dbd9 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareAttachCallback.java
@@ -18,7 +18,7 @@
 
 /**
  * Base class for Aware attach callbacks. Should be extended by applications and set when calling
- * {@link WifiAwareManager#attach(android.os.Handler, WifiAwareAttachCallback)}. These are callbacks
+ * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}. These are callbacks
  * applying to the Aware connection as a whole - not to specific publish or subscribe sessions -
  * for that see {@link WifiAwareDiscoverySessionCallback}.
  *
@@ -27,7 +27,7 @@
 public class WifiAwareAttachCallback {
     /**
      * Called when Aware attach operation
-     * {@link WifiAwareManager#attach(android.os.Handler, WifiAwareAttachCallback)}
+     * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}
      * is completed and that we can now start discovery sessions or connections.
      *
      * @param session The Aware object on which we can execute further Aware operations - e.g.
@@ -39,7 +39,7 @@
 
     /**
      * Called when Aware attach operation
-     * {@link WifiAwareManager#attach(android.os.Handler, WifiAwareAttachCallback)} failed.
+     * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)} failed.
      */
     public void onAttachFailed() {
         /* empty */
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
index 6232c14..072ccab 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareCharacteristics.java
@@ -58,7 +58,8 @@
      * message exchange. Restricts the parameters of the
      * {@link PublishConfig.Builder#setServiceSpecificInfo(byte[])},
      * {@link SubscribeConfig.Builder#setServiceSpecificInfo(byte[])}, and
-     * {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])} variants.
+     * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])}
+     * variants.
      *
      * @return A positive integer, maximum length of byte array for Aware messaging.
      */
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java b/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
index 07f7523..e8335d1 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareDiscoveryBaseSession.java
@@ -32,10 +32,10 @@
  * {@link WifiAwarePublishDiscoverySession} and {@link WifiAwareSubscribeDiscoverySession}. This
  * class provides functionality common to both publish and subscribe discovery sessions:
  * <ul>
- *     <li>Sending messages: {@link #sendMessage(Object, int, byte[])} or
- *     {@link #sendMessage(Object, int, byte[], int)} methods.
+ *     <li>Sending messages: {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[])} or
+ *     {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)} methods.
  *     <li>Creating a network-specifier when requesting a Aware connection:
- *     {@link #createNetworkSpecifier(int, Object, byte[])}.
+ *     {@link #createNetworkSpecifier(int, WifiAwareManager.PeerHandle, byte[])}.
  * </ul>
  * The {@link #destroy()} method must be called to destroy discovery sessions once they are
  * no longer needed.
@@ -62,7 +62,7 @@
 
     /**
      * Return the maximum permitted retry count when sending messages using
-     * {@link #sendMessage(Object, int, byte[], int)}.
+     * {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)}.
      *
      * @return Maximum retry count when sending messages.
      */
@@ -139,21 +139,24 @@
     /**
      * Sends a message to the specified destination. Aware messages are transmitted in the context
      * of a discovery session - executed subsequent to a publish/subscribe
-     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} event.
+     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+     * byte[], byte[])} event.
      * <p>
      *     Aware messages are not guaranteed delivery. Callbacks on
      *     {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
-     *     {@link WifiAwareDiscoverySessionCallback#onMessageSent(int)}, or transmission failed
-     *     (possibly after several retries) -
+     *     {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
+     *     failed (possibly after several retries) -
      *     {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}.
      * <p>
      *     The peer will get a callback indicating a message was received using
-     *     {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])}.
+     *     {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+     *     byte[])}.
      *
      * @param peerHandle The peer's handle for the message. Must be a result of an
-     *        {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
-     *        or
-     *        {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])} events.
+     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+     * byte[], byte[])} or
+     * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+     * byte[])} events.
      * @param messageId An arbitrary integer used by the caller to identify the message. The same
      *            integer ID will be returned in the callbacks indicating message send success or
      *            failure. The {@code messageId} is not used internally by the Aware service - it
@@ -164,8 +167,8 @@
      *            (note: no retransmissions are attempted in other failure cases). A value of 0
      *            indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}.
      */
-    public void sendMessage(@NonNull Object peerHandle, int messageId, @Nullable byte[] message,
-            int retryCount) {
+    public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId,
+            @Nullable byte[] message, int retryCount) {
         if (mTerminated) {
             Log.w(TAG, "sendMessage: called on terminated session");
             return;
@@ -183,37 +186,43 @@
     /**
      * Sends a message to the specified destination. Aware messages are transmitted in the context
      * of a discovery session - executed subsequent to a publish/subscribe
-     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} event.
+     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+     * byte[], byte[])} event.
      * <p>
      *     Aware messages are not guaranteed delivery. Callbacks on
      *     {@link WifiAwareDiscoverySessionCallback} indicate message was transmitted successfully,
-     *     {@link WifiAwareDiscoverySessionCallback#onMessageSent(int)}, or transmission failed
-     *     (possibly after several retries) -
+     *     {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
+     *     failed (possibly after several retries) -
      *     {@link WifiAwareDiscoverySessionCallback#onMessageSendFailed(int)}.
      * <p>
-     *     The peer will get a callback indicating a message was received using
-     *     {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])}.
-     * Equivalent to {@link #sendMessage(Object, int, byte[], int)} with a {@code retryCount} of
-     * 0.
+     * The peer will get a callback indicating a message was received using
+     * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+     * byte[])}.
+     * Equivalent to {@link #sendMessage(WifiAwareManager.PeerHandle, int, byte[], int)}
+     * with a {@code retryCount} of 0.
      *
      * @param peerHandle The peer's handle for the message. Must be a result of an
-     *        {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])}
-     *        or
-     *        {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])} events.
+     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+     * byte[], byte[])} or
+     * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+     * byte[])} events.
      * @param messageId An arbitrary integer used by the caller to identify the message. The same
      *            integer ID will be returned in the callbacks indicating message send success or
      *            failure. The {@code messageId} is not used internally by the Aware service - it
      *                  can be arbitrary and non-unique.
      * @param message The message to be transmitted.
      */
-    public void sendMessage(@NonNull Object peerHandle, int messageId, @Nullable byte[] message) {
+    public void sendMessage(@NonNull WifiAwareManager.PeerHandle peerHandle, int messageId,
+            @Nullable byte[] message) {
         sendMessage(peerHandle, messageId, message, 0);
     }
 
     /**
      * Start a ranging operation with the specified peers. The peer IDs are obtained from an
-     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} or
-     * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])} operation - can
+     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+     * byte[], byte[])} or
+     * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+     * byte[])} operation - can
      * only range devices which are part of an ongoing discovery session.
      *
      * @param params   RTT parameters - each corresponding to a specific peer ID (the array sizes
@@ -256,11 +265,12 @@
      * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
      * {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_RESPONDER}
      * @param peerHandle The peer's handle obtained through
-     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(Object, byte[], byte[])} or
-     * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(Object, byte[])}. On a RESPONDER
-     *               this value is used to gate the acceptance of a connection request from only
-     *               that peer. A RESPONDER may specified a null - indicating that it will accept
-     *               connection requests from any device.
+     * {@link WifiAwareDiscoverySessionCallback#onServiceDiscovered(WifiAwareManager.PeerHandle,
+     * byte[], byte[])} or
+     * {@link WifiAwareDiscoverySessionCallback#onMessageReceived(WifiAwareManager.PeerHandle,
+     * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
+     *                   from only that peer. A RESPONDER may specified a null - indicating that
+     *                   it will accept connection requests from any device.
      * @param token An arbitrary token (message) to be used to match connection initiation request
      *              to a responder setup. A RESPONDER is set up with a {@code token} which must
      *              be matched by the token provided by the INITIATOR. A null token is permitted
@@ -274,7 +284,7 @@
      * [or other varieties of that API].
      */
     public String createNetworkSpecifier(@WifiAwareManager.DataPathRole int role,
-            @Nullable Object peerHandle, @Nullable byte[] token) {
+            @Nullable WifiAwareManager.PeerHandle peerHandle, @Nullable byte[] token) {
         if (mTerminated) {
             Log.w(TAG, "createNetworkSpecifier: called on terminated session");
             return null;
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
index 9dfa24f..6331c9c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareDiscoverySessionCallback.java
@@ -26,11 +26,10 @@
  * Base class for Aware session events callbacks. Should be extended by
  * applications wanting notifications. The callbacks are set when a
  * publish or subscribe session is created using
- * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
- * WifiAwareDiscoverySessionCallback)}
- * or
- * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
- * WifiAwareDiscoverySessionCallback)} .
+ * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)} or
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)}.
  * <p>
  * A single callback is set at session creation - it cannot be replaced.
  *
@@ -62,9 +61,8 @@
 
     /**
      * Called when a publish operation is started successfully in response to a
-     * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
-     * WifiAwareDiscoverySessionCallback)}
-     * operation.
+     * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+     * android.os.Handler)} operation.
      *
      * @param session The {@link WifiAwarePublishDiscoverySession} used to control the
      *            discovery session.
@@ -75,9 +73,8 @@
 
     /**
      * Called when a subscribe operation is started successfully in response to a
-     * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
-     * WifiAwareDiscoverySessionCallback)}
-     * operation.
+     * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+     * android.os.Handler)} operation.
      *
      * @param session The {@link WifiAwareSubscribeDiscoverySession} used to control the
      *            discovery session.
@@ -98,12 +95,10 @@
 
     /**
      * Called when a publish or subscribe discovery session cannot be created:
-     * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
-     * WifiAwareDiscoverySessionCallback)}
-     * or
-     * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
-     * WifiAwareDiscoverySessionCallback)},
-     * or when a configuration update fails:
+     * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+     * android.os.Handler)} or
+     * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+     * android.os.Handler)}, or when a configuration update fails:
      * {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} or
      * {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}.
      * <p>
@@ -138,13 +133,14 @@
      * @param matchFilter The filter (Tx on advertiser and Rx on listener) which
      *            resulted in this service discovery.
      */
-    public void onServiceDiscovered(Object peerHandle, byte[] serviceSpecificInfo,
-            byte[] matchFilter) {
+    public void onServiceDiscovered(WifiAwareManager.PeerHandle peerHandle,
+            byte[] serviceSpecificInfo, byte[] matchFilter) {
         /* empty */
     }
 
     /**
-     * Called in response to {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])}
+     * Called in response to
+     * {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int, byte[])}
      * when a message is transmitted successfully - i.e. when it was received successfully by the
      * peer (corresponds to an ACK being received).
      * <p>
@@ -154,18 +150,18 @@
      *
      * @param messageId The arbitrary message ID specified when sending the message.
      */
-    public void onMessageSent(@SuppressWarnings("unused") int messageId) {
+    public void onMessageSendSucceeded(@SuppressWarnings("unused") int messageId) {
         /* empty */
     }
 
     /**
      * Called when message transmission fails - when no ACK is received from the peer.
      * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using
-     * the {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[], int)} method) -
-     * this event is received after all retries are exhausted.
+     * the {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int,
+     * byte[], int)} method) - this event is received after all retries are exhausted.
      * <p>
      * Note that either this callback or
-     * {@link WifiAwareDiscoverySessionCallback#onMessageSent(int)} will be received
+     * {@link WifiAwareDiscoverySessionCallback#onMessageSendSucceeded(int)} will be received
      * - never both.
      *
      * @param messageId The arbitrary message ID specified when sending the message.
@@ -176,13 +172,14 @@
 
     /**
      * Called when a message is received from a discovery session peer - in response to the
-     * peer's {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])} or
-     * {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[], int)}.
+     * peer's {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle, int,
+     * byte[])} or {@link WifiAwareDiscoveryBaseSession#sendMessage(WifiAwareManager.PeerHandle,
+     * int, byte[], int)}.
      *
      * @param peerHandle An opaque handle to the peer matching our discovery operation.
      * @param message A byte array containing the message.
      */
-    public void onMessageReceived(Object peerHandle, byte[] message) {
+    public void onMessageReceived(WifiAwareManager.PeerHandle peerHandle, byte[] message) {
         /* empty */
     }
 }
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 10b70ab..a34ef47 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -56,14 +56,14 @@
  * The class provides access to:
  * <ul>
  * <li>Initialize a Aware cluster (peer-to-peer synchronization). Refer to
- * {@link #attach(Handler, WifiAwareAttachCallback)}.
+ * {@link #attach(WifiAwareAttachCallback, Handler)}.
  * <li>Create discovery sessions (publish or subscribe sessions). Refer to
- * {@link WifiAwareSession#publish(Handler, PublishConfig, WifiAwareDiscoverySessionCallback)} and
- * {@link WifiAwareSession#subscribe(Handler, SubscribeConfig, WifiAwareDiscoverySessionCallback)}.
+ * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)} and
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback, Handler)}.
  * <li>Create a Aware network specifier to be used with
  * {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}
  * to set-up a Aware connection with a peer. Refer to
- * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])} and
+ * {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, PeerHandle, byte[])} and
  * {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])}.
  * </ul>
  * <p>
@@ -73,7 +73,7 @@
  *     broadcast. Note that this broadcast is not sticky - you should register for it and then
  *     check the above API to avoid a race condition.
  * <p>
- *     An application must use {@link #attach(Handler, WifiAwareAttachCallback)} to initialize a
+ *     An application must use {@link #attach(WifiAwareAttachCallback, Handler)} to initialize a
  *     Aware cluster - before making any other Aware operation. Aware cluster membership is a
  *     device-wide operation - the API guarantees that the device is in a cluster or joins a
  *     Aware cluster (or starts one if none can be found). Information about attach success (or
@@ -86,12 +86,11 @@
  *     application detaches.
  * <p>
  *     Once a Aware attach is confirmed use the
- *     {@link WifiAwareSession#publish(Handler, PublishConfig, WifiAwareDiscoverySessionCallback)}
+ *     {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback, Handler)}
  *     or
- *     {@link WifiAwareSession#subscribe(Handler, SubscribeConfig,
- *     WifiAwareDiscoverySessionCallback)}
- *     to create publish or subscribe Aware discovery sessions. Events are called on the provided
- *     callback object {@link WifiAwareDiscoverySessionCallback}. Specifically, the
+ *     {@link WifiAwareSession#subscribe(SubscribeConfig, WifiAwareDiscoverySessionCallback,
+ *     Handler)} to create publish or subscribe Aware discovery sessions. Events are called on the
+ *     provided callback object {@link WifiAwareDiscoverySessionCallback}. Specifically, the
  *     {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}
  *     and
  *     {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(
@@ -102,7 +101,7 @@
  *     the session {@link WifiAwarePublishDiscoverySession#updatePublish(PublishConfig)} and
  *     {@link WifiAwareSubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can
  *     also be used to send messages using the
- *     {@link WifiAwareDiscoveryBaseSession#sendMessage(Object, int, byte[])} APIs. When an
+ *     {@link WifiAwareDiscoveryBaseSession#sendMessage(PeerHandle, int, byte[])} APIs. When an
  *     application is finished with a discovery session it <b>must</b> terminate it using the
  *     {@link WifiAwareDiscoveryBaseSession#destroy()} API.
  * <p>
@@ -115,7 +114,7 @@
  *        {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
  *        <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using
  *        {@link WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])} or
- *        {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])}.
+ *        {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, PeerHandle, byte[])}.
  *    </ul>
  *
  * @hide PROPOSED_AWARE_API
@@ -225,7 +224,7 @@
      * Connection creation role is that of INITIATOR. Used to create a network specifier string
      * when requesting a Aware network.
      *
-     * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])
+     * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, PeerHandle, byte[])
      * @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
      */
     public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0;
@@ -234,7 +233,7 @@
      * Connection creation role is that of RESPONDER. Used to create a network specifier string
      * when requesting a Aware network.
      *
-     * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])
+     * @see WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, PeerHandle, byte[])
      * @see WifiAwareSession#createNetworkSpecifier(int, byte[], byte[])
      */
     public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1;
@@ -326,13 +325,13 @@
      * then this function will simply indicate success immediately using the same {@code
      * attachCallback}.
      *
+     * @param attachCallback A callback for attach events, extended from
+     * {@link WifiAwareAttachCallback}.
      * @param handler The Handler on whose thread to execute the callbacks of the {@code
      * attachCallback} object. If a null is provided then the application's main thread will be
      *                used.
-     * @param attachCallback A callback for attach events, extended from
-     * {@link WifiAwareAttachCallback}.
      */
-    public void attach(@Nullable Handler handler, @NonNull WifiAwareAttachCallback attachCallback) {
+    public void attach(@NonNull WifiAwareAttachCallback attachCallback, @Nullable Handler handler) {
         attach(handler, null, attachCallback, null);
     }
 
@@ -352,20 +351,21 @@
      * on startup and whenever it is updated (it is randomized at regular intervals for privacy).
      * The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
      * permission to execute this attach request. Otherwise, use the
-     * {@link #attach(Handler, WifiAwareAttachCallback)} version. Note that aside from permission
+     * {@link #attach(WifiAwareAttachCallback, Handler)} version. Note that aside from permission
      * requirements this listener will wake up the host at regular intervals causing higher power
      * consumption, do not use it unless the information is necessary (e.g. for OOB discovery).
      *
-     * @param handler The Handler on whose thread to execute the callbacks of the {@code
-     * attachCallback} and {@code identityChangedListener} objects. If a null is provided then the
-     *                application's main thread will be used.
      * @param attachCallback A callback for attach events, extended from
      * {@link WifiAwareAttachCallback}.
      * @param identityChangedListener A listener for changed identity, extended from
      * {@link WifiAwareIdentityChangedListener}.
+     * @param handler The Handler on whose thread to execute the callbacks of the {@code
+     * attachCallback} and {@code identityChangedListener} objects. If a null is provided then the
+     *                application's main thread will be used.
      */
-    public void attach(@Nullable Handler handler, @NonNull WifiAwareAttachCallback attachCallback,
-            @NonNull WifiAwareIdentityChangedListener identityChangedListener) {
+    public void attach(@NonNull WifiAwareAttachCallback attachCallback,
+            @NonNull WifiAwareIdentityChangedListener identityChangedListener,
+            @Nullable Handler handler) {
         attach(handler, null, attachCallback, identityChangedListener);
     }
 
@@ -481,7 +481,7 @@
     }
 
     /** @hide */
-    public void sendMessage(int clientId, int sessionId, Object peerHandle, byte[] message,
+    public void sendMessage(int clientId, int sessionId, PeerHandle peerHandle, byte[] message,
             int messageId, int retryCount) {
         if (peerHandle == null) {
             throw new IllegalArgumentException(
@@ -490,13 +490,13 @@
 
         if (VDBG) {
             Log.v(TAG, "sendMessage(): clientId=" + clientId + ", sessionId=" + sessionId
-                    + ", peerHandle=" + ((OpaquePeerHandle) peerHandle).peerId + ", messageId="
+                    + ", peerHandle=" + peerHandle.peerId + ", messageId="
                     + messageId + ", retryCount=" + retryCount);
         }
 
         try {
-            mService.sendMessage(clientId, sessionId, ((OpaquePeerHandle) peerHandle).peerId,
-                    message, messageId, retryCount);
+            mService.sendMessage(clientId, sessionId, peerHandle.peerId, message, messageId,
+                    retryCount);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -524,12 +524,12 @@
     }
 
     /** @hide */
-    public String createNetworkSpecifier(int clientId, int role, int sessionId, Object peerHandle,
-            byte[] token) {
+    public String createNetworkSpecifier(int clientId, int role, int sessionId,
+            PeerHandle peerHandle, byte[] token) {
         if (VDBG) {
             Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
-                    + ", peerHandle=" + ((peerHandle == null) ? peerHandle
-                    : ((OpaquePeerHandle) peerHandle).peerId) + ", token=" + token);
+                    + ", peerHandle=" + ((peerHandle == null) ? peerHandle : peerHandle.peerId)
+                    + ", token=" + token);
         }
 
         int type;
@@ -569,7 +569,7 @@
             json.put(NETWORK_SPECIFIER_KEY_CLIENT_ID, clientId);
             json.put(NETWORK_SPECIFIER_KEY_SESSION_ID, sessionId);
             if (peerHandle != null) {
-                json.put(NETWORK_SPECIFIER_KEY_PEER_ID, ((OpaquePeerHandle) peerHandle).peerId);
+                json.put(NETWORK_SPECIFIER_KEY_PEER_ID, peerHandle.peerId);
             }
             if (token != null) {
                 json.put(NETWORK_SPECIFIER_KEY_TOKEN,
@@ -876,18 +876,18 @@
                             break;
                         case CALLBACK_MATCH:
                             mOriginalCallback.onServiceDiscovered(
-                                    new OpaquePeerHandle(msg.arg1),
+                                    new PeerHandle(msg.arg1),
                                     msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
                                     msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2));
                             break;
                         case CALLBACK_MESSAGE_SEND_SUCCESS:
-                            mOriginalCallback.onMessageSent(msg.arg1);
+                            mOriginalCallback.onMessageSendSucceeded(msg.arg1);
                             break;
                         case CALLBACK_MESSAGE_SEND_FAIL:
                             mOriginalCallback.onMessageSendFailed(msg.arg1);
                             break;
                         case CALLBACK_MESSAGE_RECEIVED:
-                            mOriginalCallback.onMessageReceived(new OpaquePeerHandle(msg.arg1),
+                            mOriginalCallback.onMessageReceived(new PeerHandle(msg.arg1),
                                     (byte[]) msg.obj);
                             break;
                     }
@@ -1019,12 +1019,14 @@
         }
     }
 
-    /** @hide */
-    public static class OpaquePeerHandle {
-        public OpaquePeerHandle(int peerId) {
+    /** @hide PROPOSED_AWARE_API */
+    public static class PeerHandle {
+        /** @hide */
+        public PeerHandle(int peerId) {
             this.peerId = peerId;
         }
 
+        /** @hide */
         public int peerId;
     }
 }
diff --git a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java b/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
index 610a92c..68786d1 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwarePublishDiscoverySession.java
@@ -21,9 +21,8 @@
 
 /**
  * A class representing a Aware publish session. Created when
- * {@link WifiAwareSession#publish(android.os.Handler, PublishConfig,
- * WifiAwareDiscoverySessionCallback)}
- * is called and a discovery session is created and returned in
+ * {@link WifiAwareSession#publish(PublishConfig, WifiAwareDiscoverySessionCallback,
+ * android.os.Handler)} is called and a discovery session is created and returned in
  * {@link WifiAwareDiscoverySessionCallback#onPublishStarted(WifiAwarePublishDiscoverySession)}. See
  * baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}. This
  * object allows updating an existing/running publish discovery session using
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index 357bd43..acb60a4 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -65,7 +65,7 @@
      * session-wide destroy.
      * <p>
      * An application may re-attach after a destroy using
-     * {@link WifiAwareManager#attach(Handler, WifiAwareAttachCallback)} .
+     * {@link WifiAwareManager#attach(WifiAwareAttachCallback, Handler)} .
      */
     public void destroy() {
         WifiAwareManager mgr = mMgr.get();
@@ -116,15 +116,15 @@
      * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
      * permission to start a publish discovery session.
      *
-     * @param handler The Handler on whose thread to execute the callbacks of the {@code
-     * callback} object. If a null is provided then the application's main thread will be used.
      * @param publishConfig The {@link PublishConfig} specifying the
      *            configuration of the requested publish session.
      * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for
      *                 session event callbacks.
+     * @param handler The Handler on whose thread to execute the callbacks of the {@code
+     * callback} object. If a null is provided then the application's main thread will be used.
      */
-    public void publish(@Nullable Handler handler, @NonNull PublishConfig publishConfig,
-            @NonNull WifiAwareDiscoverySessionCallback callback) {
+    public void publish(@NonNull PublishConfig publishConfig,
+            @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) {
         WifiAwareManager mgr = mMgr.get();
         if (mgr == null) {
             Log.e(TAG, "publish: called post GC on WifiAwareManager");
@@ -162,15 +162,15 @@
      * <p>The application must have the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
      * permission to start a subscribe discovery session.
      *
-     * @param handler The Handler on whose thread to execute the callbacks of the {@code
-     * callback} object. If a null is provided then the application's main thread will be used.
      * @param subscribeConfig The {@link SubscribeConfig} specifying the
      *            configuration of the requested subscribe session.
      * @param callback A {@link WifiAwareDiscoverySessionCallback} derived object to be used for
      *                 session event callbacks.
+     * @param handler The Handler on whose thread to execute the callbacks of the {@code
+     * callback} object. If a null is provided then the application's main thread will be used.
      */
-    public void subscribe(@Nullable Handler handler, @NonNull SubscribeConfig subscribeConfig,
-            @NonNull WifiAwareDiscoverySessionCallback callback) {
+    public void subscribe(@NonNull SubscribeConfig subscribeConfig,
+            @NonNull WifiAwareDiscoverySessionCallback callback, @Nullable Handler handler) {
         WifiAwareManager mgr = mMgr.get();
         if (mgr == null) {
             Log.e(TAG, "publish: called post GC on WifiAwareManager");
@@ -193,7 +193,8 @@
      *     This API is targeted for applications which can obtain the peer MAC address using OOB
      *     (out-of-band) discovery. Aware discovery does not provide the MAC address of the peer -
      *     when using Aware discovery use the alternative network specifier method -
-     *     {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int, Object, byte[])}.
+     *     {@link WifiAwareDiscoveryBaseSession#createNetworkSpecifier(int,
+     *     WifiAwareManager.PeerHandle, byte[])}.
      *
      * @param role  The role of this device:
      *              {@link WifiAwareManager#WIFI_AWARE_DATA_PATH_ROLE_INITIATOR} or
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java b/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
index 7c48f54..a0ec809 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSubscribeDiscoverySession.java
@@ -21,8 +21,8 @@
 
 /**
  * A class representing a Aware subscribe session. Created when
- * {@link WifiAwareSession#subscribe(android.os.Handler, SubscribeConfig,
- * WifiAwareDiscoverySessionCallback)}
+ * {@link WifiAwareSession#subscribe(SubscribeConfig,
+ * WifiAwareDiscoverySessionCallback, android.os.Handler)}
  * is called and a discovery session is created and returned in
  * {@link WifiAwareDiscoverySessionCallback#onSubscribeStarted(WifiAwareSubscribeDiscoverySession)}.
  * See baseline functionality of all discovery sessions in {@link WifiAwareDiscoveryBaseSession}.
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index a62a0fb..643753a 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -36,6 +36,27 @@
     public HomeSP homeSp = null;
     public Credential credential = null;
 
+    /**
+     * Constructor for creating PasspointConfiguration with default values.
+     */
+    public PasspointConfiguration() {}
+
+    /**
+     * Copy constructor.
+     *
+     * @param source The source to copy from
+     */
+    public PasspointConfiguration(PasspointConfiguration source) {
+        if (source != null) {
+            if (source.homeSp != null) {
+                homeSp = new HomeSP(source.homeSp);
+            }
+            if (source.credential != null) {
+                credential = new Credential(source.credential);
+            }
+        }
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 57e65eb..790dfaf 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -109,6 +109,25 @@
          */
         public String nonEapInnerMethod = null;
 
+        /**
+         * Constructor for creating UserCredential with default values.
+         */
+        public UserCredential() {}
+
+        /**
+         * Copy constructor.
+         *
+         * @param source The source to copy from
+         */
+        public UserCredential(UserCredential source) {
+            if (source != null) {
+                username = source.username;
+                password = source.password;
+                eapType = source.eapType;
+                nonEapInnerMethod = source.nonEapInnerMethod;
+            }
+        }
+
         @Override
         public int describeContents() {
             return 0;
@@ -221,6 +240,26 @@
          */
         public byte[] certSha256FingerPrint = null;
 
+        /**
+         * Constructor for creating CertificateCredential with default values.
+         */
+        public CertificateCredential() {}
+
+        /**
+         * Copy constructor.
+         *
+         * @param source The source to copy from
+         */
+        public CertificateCredential(CertificateCredential source) {
+            if (source != null) {
+                certType = source.certType;
+                if (source.certSha256FingerPrint != null) {
+                    certSha256FingerPrint = Arrays.copyOf(source.certSha256FingerPrint,
+                                                          source.certSha256FingerPrint.length);
+                }
+            }
+        }
+
         @Override
         public int describeContents() {
             return 0;
@@ -307,6 +346,23 @@
          */
         public int eapType = Integer.MIN_VALUE;
 
+        /**
+         * Constructor for creating SimCredential with default values.
+         */
+        public SimCredential() {}
+
+        /**
+         * Copy constructor
+         *
+         * @param source The source to copy from
+         */
+        public SimCredential(SimCredential source) {
+            if (source != null) {
+                imsi = source.imsi;
+                eapType = source.eapType;
+            }
+        }
+
         @Override
         public int describeContents() {
             return 0;
@@ -422,6 +478,37 @@
      */
     public PrivateKey clientPrivateKey = null;
 
+    /**
+     * Constructor for creating Credential with default values.
+     */
+    public Credential() {}
+
+    /**
+     * Copy constructor.
+     *
+     * @param source The source to copy from
+     */
+    public Credential(Credential source) {
+        if (source != null) {
+            realm = source.realm;
+            if (source.userCredential != null) {
+                userCredential = new UserCredential(source.userCredential);
+            }
+            if (source.certCredential != null) {
+                certCredential = new CertificateCredential(source.certCredential);
+            }
+            if (source.simCredential != null) {
+                simCredential = new SimCredential(source.simCredential);
+            }
+            if (source.clientCertificateChain != null) {
+                clientCertificateChain = Arrays.copyOf(source.clientCertificateChain,
+                                                       source.clientCertificateChain.length);
+            }
+            caCertificate = source.caCertificate;
+            clientPrivateKey = source.clientPrivateKey;
+        }
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
index 5837c06..d4a5792 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
@@ -53,6 +53,27 @@
      */
     public long[] roamingConsortiumOIs = null;
 
+    /**
+     * Constructor for creating HomeSP with default values.
+     */
+    public HomeSP() {}
+
+    /**
+     * Copy constructor.
+     *
+     * @param source The source to copy from
+     */
+    public HomeSP(HomeSP source) {
+        if (source != null) {
+            fqdn = source.fqdn;
+            friendlyName = source.friendlyName;
+            if (source.roamingConsortiumOIs != null) {
+                roamingConsortiumOIs = Arrays.copyOf(source.roamingConsortiumOIs,
+                                                     source.roamingConsortiumOIs.length);
+            }
+        }
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index b4a3acf..2350d32 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -33,6 +33,11 @@
 @SmallTest
 public class PasspointConfigurationTest {
 
+    /**
+     * Utility function for creating a {@link android.net.wifi.hotspot2.pps.HomeSP}.
+     *
+     * @return {@link android.net.wifi.hotspot2.pps.HomeSP}
+     */
     private static HomeSP createHomeSp() {
         HomeSP homeSp = new HomeSP();
         homeSp.fqdn = "fqdn";
@@ -41,6 +46,11 @@
         return homeSp;
     }
 
+    /**
+     * Utility function for creating a {@link android.net.wifi.hotspot2.pps.Credential}.
+     *
+     * @return {@link android.net.wifi.hotspot2.pps.Credential}
+     */
     private static Credential createCredential() {
         Credential cred = new Credential();
         cred.realm = "realm";
@@ -55,6 +65,12 @@
         return cred;
     }
 
+    /**
+     * Verify parcel write and read consistency for the given configuration.
+     *
+     * @param writeConfig The configuration to verify
+     * @throws Exception
+     */
     private static void verifyParcel(PasspointConfiguration writeConfig) throws Exception {
         Parcel parcel = Parcel.obtain();
         writeConfig.writeToParcel(parcel, 0);
@@ -77,6 +93,7 @@
 
     /**
      * Verify parcel read/write for a configuration that contained both HomeSP and Credential.
+     *
      * @throws Exception
      */
     @Test
@@ -158,4 +175,30 @@
         config.credential = createCredential();
         assertTrue(config.validate());
     }
-}
\ No newline at end of file
+
+    /**
+     * Verify that copy constructor works when pass in a null source.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateCopyConstructorWithNullSource() throws Exception {
+        PasspointConfiguration copyConfig = new PasspointConfiguration(null);
+        PasspointConfiguration defaultConfig = new PasspointConfiguration();
+        assertTrue(copyConfig.equals(defaultConfig));
+    }
+
+    /**
+     * Verify that copy constructor works when pass in a valid source.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateCopyConstructorWithValidSource() throws Exception {
+        PasspointConfiguration sourceConfig = new PasspointConfiguration();
+        sourceConfig.homeSp = createHomeSp();
+        sourceConfig.credential = createCredential();
+        PasspointConfiguration copyConfig = new PasspointConfiguration(sourceConfig);
+        assertTrue(copyConfig.equals(sourceConfig));
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index 223aa52..9c8b749 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -470,4 +470,52 @@
         cred.simCredential.eapType = EAPConstants.EAP_SIM;
         assertFalse(cred.validate());
     }
+
+    /**
+     * Verify that copy constructor works when pass in a null source.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateCopyConstructorWithNullSource() throws Exception {
+        Credential copyCred = new Credential(null);
+        Credential defaultCred = new Credential();
+        assertTrue(copyCred.equals(defaultCred));
+    }
+
+    /**
+     * Verify that copy constructor works when pass in a source with user credential.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateCopyConstructorWithSourceWithUserCred() throws Exception {
+        Credential sourceCred = createCredentialWithUserCredential();
+        Credential copyCred = new Credential(sourceCred);
+        assertTrue(copyCred.equals(sourceCred));
+    }
+
+    /**
+     * Verify that copy constructor works when pass in a source with certificate credential.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateCopyConstructorWithSourceWithCertCred() throws Exception {
+        Credential sourceCred = createCredentialWithCertificateCredential();
+        Credential copyCred = new Credential(sourceCred);
+        assertTrue(copyCred.equals(sourceCred));
+    }
+
+    /**
+     * Verify that copy constructor works when pass in a source with SIM credential.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateCopyConstructorWithSourceWithSimCred() throws Exception {
+        Credential sourceCred = createCredentialWithSimCredential();
+        Credential copyCred = new Credential(sourceCred);
+        assertTrue(copyCred.equals(sourceCred));
+    }
 }
\ No newline at end of file
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
index fff1477..c707993 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
@@ -118,4 +118,31 @@
         homeSp.roamingConsortiumOIs = new long[] {0x55, 0x66};
         assertTrue(homeSp.validate());
     }
+
+    /**
+     * Verify that copy constructor works when pass in a null source.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateCopyConstructorFromNullSource() throws Exception {
+        HomeSP copySp = new HomeSP(null);
+        HomeSP defaultSp = new HomeSP();
+        assertTrue(copySp.equals(defaultSp));
+    }
+
+    /**
+     * Verify that copy constructor works when pass in a valid source.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateCopyConstructorFromValidSource() throws Exception {
+        HomeSP sourceSp = new HomeSP();
+        sourceSp.fqdn = "fqdn";
+        sourceSp.friendlyName = "friendlyName";
+        sourceSp.roamingConsortiumOIs = new long[] {0x55, 0x66};
+        HomeSP copySp = new HomeSP(sourceSp);
+        assertTrue(copySp.equals(sourceSp));
+    }
 }