Merge "Fix EGLImage memory leak"
diff --git a/Android.mk b/Android.mk
index 4af2ce0..47efddd 100644
--- a/Android.mk
+++ b/Android.mk
@@ -126,6 +126,7 @@
 	core/java/android/bluetooth/IBluetoothGatt.aidl \
 	core/java/android/bluetooth/IBluetoothGattCallback.aidl \
 	core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \
+	core/java/android/bluetooth/le/IAdvertiserCallback.aidl \
 	core/java/android/content/IClipboard.aidl \
 	core/java/android/content/IContentService.aidl \
 	core/java/android/content/IIntentReceiver.aidl \
@@ -491,6 +492,12 @@
 			$(framework_res_source_path)/android/Manifest.java \
 			$(framework_res_source_path)/com/android/internal/R.java
 
+# Make sure that R.java and Manifest.java are built before we build
+# the source for this library.
+framework_res_R_stamp := \
+	$(call intermediates-dir-for,APPS,framework-res,,COMMON)/src/R.stamp
+LOCAL_ADDITIONAL_DEPENDENCIES := $(framework_res_R_stamp)
+
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_JAVA_LIBRARIES := core-oj core-libart core-lambda-stubs conscrypt okhttp core-junit bouncycastle ext
 LOCAL_STATIC_JAVA_LIBRARIES := framework-protos
@@ -506,15 +513,8 @@
 endif
 
 include $(BUILD_JAVA_LIBRARY)
+
 framework_module := $(LOCAL_INSTALLED_MODULE)
-
-# Make sure that R.java and Manifest.java are built before we build
-# the source for this library.
-framework_res_R_stamp := \
-	$(call intermediates-dir-for,APPS,framework-res,,COMMON)/src/R.stamp
-$(full_classes_compiled_jar): $(framework_res_R_stamp)
-$(built_dex_intermediate): $(framework_res_R_stamp)
-
 $(framework_module): | $(dir $(framework_module))framework-res.apk
 
 framework_built := $(call java-lib-deps,framework)
@@ -895,7 +895,7 @@
 
 ## SDK version identifiers used in the published docs
   # major[.minor] version for current SDK. (full releases only)
-framework_docs_SDK_VERSION:=6.0
+framework_docs_SDK_VERSION:=7.0
   # release version (ie "Release x")  (full releases only)
 framework_docs_SDK_REL_ID:=1
 
@@ -904,7 +904,7 @@
 		-hdf sdk.preview.version 5 \
 		-hdf sdk.version $(framework_docs_SDK_VERSION) \
 		-hdf sdk.rel.id $(framework_docs_SDK_REL_ID) \
-		-hdf sdk.preview 1
+		-hdf sdk.preview 0
 
 # ====  the api stubs and current.xml ===========================
 include $(CLEAR_VARS)
@@ -1099,12 +1099,12 @@
 		-hdf android.whichdoc offline \
 		-referenceonly
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk-dev
 
 include $(BUILD_DROIDDOC)
 
 static_doc_index_redirect := $(out_dir)/index.html
-$(static_doc_index_redirect): $(LOCAL_PATH)/docs/docs-preview-index.html
+$(static_doc_index_redirect): $(LOCAL_PATH)/docs/docs-documentation-redirect.html
 	$(copy-file-to-target)
 
 $(full_target): $(static_doc_index_redirect)
diff --git a/apct-tests/perftests/graphics/src/android/graphics/perftests/RenderNodePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
similarity index 100%
rename from apct-tests/perftests/graphics/src/android/graphics/perftests/RenderNodePerfTest.java
rename to apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
diff --git a/apct-tests/perftests/core/src/android/widget/LayoutPerfTest.java b/apct-tests/perftests/core/src/android/widget/LayoutPerfTest.java
index ea412eb..d570ef3 100644
--- a/apct-tests/perftests/core/src/android/widget/LayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/LayoutPerfTest.java
@@ -78,29 +78,31 @@
 
     @Test
     @UiThreadTest
-    public void testLayoutPerf() {
-        assertTrue("We should be running on the main thread",
-                Looper.getMainLooper().getThread() == Thread.currentThread());
-        assertTrue("We should be running on the main thread",
-                Looper.myLooper() == Looper.getMainLooper());
+    public void testLayoutPerf() throws Throwable {
+        mActivityRule.runOnUiThread(() -> {
+            assertTrue("We should be running on the main thread",
+                    Looper.getMainLooper().getThread() == Thread.currentThread());
+            assertTrue("We should be running on the main thread",
+                    Looper.myLooper() == Looper.getMainLooper());
 
-        Activity activity = mActivityRule.getActivity();
-        activity.setContentView(mLayoutId);
+            Activity activity = mActivityRule.getActivity();
+            activity.setContentView(mLayoutId);
 
-        ViewGroup viewGroup = (ViewGroup) activity.findViewById(mViewId);
+            ViewGroup viewGroup = (ViewGroup) activity.findViewById(mViewId);
 
-        List<View> allNodes = gatherViewTree(viewGroup);
-        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+            List<View> allNodes = gatherViewTree(viewGroup);
+            BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
 
-        int length = mMeasureSpecs.length;
-        while (state.keepRunning()) {
-            for (int i = 0; i < length; i++) {
-                // The overhead of this call is ignorable, like within 1% difference.
-                requestLayoutForAllNodes(allNodes);
+            int length = mMeasureSpecs.length;
+            while (state.keepRunning()) {
+                for (int i = 0; i < length; i++) {
+                    // The overhead of this call is ignorable, like within 1% difference.
+                    requestLayoutForAllNodes(allNodes);
 
-                viewGroup.measure(mMeasureSpecs[i % length], mMeasureSpecs[i % length]);
-                viewGroup.layout(0, 0, viewGroup.getMeasuredWidth(), viewGroup.getMeasuredHeight());
+                    viewGroup.measure(mMeasureSpecs[i % length], mMeasureSpecs[i % length]);
+                    viewGroup.layout(0, 0, viewGroup.getMeasuredWidth(), viewGroup.getMeasuredHeight());
+                }
             }
-        }
+        });
     }
 }
diff --git a/api/current.txt b/api/current.txt
index c92df62..0a76070 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -50725,12 +50725,14 @@
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public A[] getAnnotationsByType(java.lang.Class<A>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+    method public A getDeclaredAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
@@ -50774,6 +50776,7 @@
     method public boolean isPrimitive();
     method public boolean isSynthetic();
     method public T newInstance() throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public java.lang.String toGenericString();
   }
 
   public class ClassCastException extends java.lang.RuntimeException {
@@ -52172,7 +52175,6 @@
 
   public final class Field extends java.lang.reflect.AccessibleObject implements java.lang.reflect.Member {
     method public java.lang.Object get(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
-    method public A getAnnotation(java.lang.Class<A>);
     method public boolean getBoolean(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
     method public byte getByte(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
     method public char getChar(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
@@ -52204,7 +52206,7 @@
     method public abstract java.lang.reflect.Type getGenericComponentType();
   }
 
-  public abstract interface GenericDeclaration {
+  public abstract interface GenericDeclaration implements java.lang.reflect.AnnotatedElement {
     method public abstract java.lang.reflect.TypeVariable<?>[] getTypeParameters();
   }
 
@@ -52272,6 +52274,7 @@
     method public static boolean isTransient(int);
     method public static boolean isVolatile(int);
     method public static int methodModifiers();
+    method public static int parameterModifiers();
     method public static java.lang.String toString(int);
     field public static final int ABSTRACT = 1024; // 0x400
     field public static final int FINAL = 16; // 0x10
@@ -55245,6 +55248,12 @@
   }
 
   public static abstract interface KeyStore.Entry {
+    method public default java.util.Set<java.security.KeyStore.Entry.Attribute> getAttributes();
+  }
+
+  public static abstract interface KeyStore.Entry.Attribute {
+    method public abstract java.lang.String getName();
+    method public abstract java.lang.String getValue();
   }
 
   public static abstract interface KeyStore.LoadStoreParameter {
@@ -55253,11 +55262,15 @@
 
   public static class KeyStore.PasswordProtection implements javax.security.auth.Destroyable java.security.KeyStore.ProtectionParameter {
     ctor public KeyStore.PasswordProtection(char[]);
+    ctor public KeyStore.PasswordProtection(char[], java.lang.String, java.security.spec.AlgorithmParameterSpec);
     method public synchronized char[] getPassword();
+    method public java.lang.String getProtectionAlgorithm();
+    method public java.security.spec.AlgorithmParameterSpec getProtectionParameters();
   }
 
   public static final class KeyStore.PrivateKeyEntry implements java.security.KeyStore.Entry {
     ctor public KeyStore.PrivateKeyEntry(java.security.PrivateKey, java.security.cert.Certificate[]);
+    ctor public KeyStore.PrivateKeyEntry(java.security.PrivateKey, java.security.cert.Certificate[], java.util.Set<java.security.KeyStore.Entry.Attribute>);
     method public java.security.cert.Certificate getCertificate();
     method public java.security.cert.Certificate[] getCertificateChain();
     method public java.security.PrivateKey getPrivateKey();
@@ -55268,11 +55281,13 @@
 
   public static final class KeyStore.SecretKeyEntry implements java.security.KeyStore.Entry {
     ctor public KeyStore.SecretKeyEntry(javax.crypto.SecretKey);
+    ctor public KeyStore.SecretKeyEntry(javax.crypto.SecretKey, java.util.Set<java.security.KeyStore.Entry.Attribute>);
     method public javax.crypto.SecretKey getSecretKey();
   }
 
   public static final class KeyStore.TrustedCertificateEntry implements java.security.KeyStore.Entry {
     ctor public KeyStore.TrustedCertificateEntry(java.security.cert.Certificate);
+    ctor public KeyStore.TrustedCertificateEntry(java.security.cert.Certificate, java.util.Set<java.security.KeyStore.Entry.Attribute>);
     method public java.security.cert.Certificate getTrustedCertificate();
   }
 
@@ -55408,10 +55423,11 @@
     method public abstract boolean equals(java.lang.Object);
     method public abstract java.lang.String getName();
     method public abstract int hashCode();
+    method public default boolean implies(javax.security.auth.Subject);
     method public abstract java.lang.String toString();
   }
 
-  public abstract interface PrivateKey implements java.security.Key {
+  public abstract interface PrivateKey implements javax.security.auth.Destroyable java.security.Key {
     field public static final long serialVersionUID = 6034044314589513430L; // 0x53bd3b559a12c6d6L
   }
 
@@ -55863,6 +55879,7 @@
     method public abstract java.lang.String toString();
     method public abstract void verify(java.security.PublicKey) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
     method public abstract void verify(java.security.PublicKey, java.lang.String) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
+    method public void verify(java.security.PublicKey, java.security.Provider) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.SignatureException;
     method protected java.lang.Object writeReplace() throws java.io.ObjectStreamException;
   }
 
@@ -56221,7 +56238,6 @@
     method public javax.security.auth.x500.X500Principal getSubjectX500Principal();
     method public abstract byte[] getTBSCertificate() throws java.security.cert.CertificateEncodingException;
     method public abstract int getVersion();
-    method public void verify(java.security.PublicKey, java.security.Provider) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.SignatureException;
   }
 
   public abstract interface X509Extension {
diff --git a/api/system-current.txt b/api/system-current.txt
index 6cc5dac..83cb79a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -54253,12 +54253,14 @@
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public A[] getAnnotationsByType(java.lang.Class<A>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+    method public A getDeclaredAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
@@ -54302,6 +54304,7 @@
     method public boolean isPrimitive();
     method public boolean isSynthetic();
     method public T newInstance() throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public java.lang.String toGenericString();
   }
 
   public class ClassCastException extends java.lang.RuntimeException {
@@ -55700,7 +55703,6 @@
 
   public final class Field extends java.lang.reflect.AccessibleObject implements java.lang.reflect.Member {
     method public java.lang.Object get(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
-    method public A getAnnotation(java.lang.Class<A>);
     method public boolean getBoolean(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
     method public byte getByte(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
     method public char getChar(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
@@ -55732,7 +55734,7 @@
     method public abstract java.lang.reflect.Type getGenericComponentType();
   }
 
-  public abstract interface GenericDeclaration {
+  public abstract interface GenericDeclaration implements java.lang.reflect.AnnotatedElement {
     method public abstract java.lang.reflect.TypeVariable<?>[] getTypeParameters();
   }
 
@@ -55800,6 +55802,7 @@
     method public static boolean isTransient(int);
     method public static boolean isVolatile(int);
     method public static int methodModifiers();
+    method public static int parameterModifiers();
     method public static java.lang.String toString(int);
     field public static final int ABSTRACT = 1024; // 0x400
     field public static final int FINAL = 16; // 0x10
@@ -58773,6 +58776,12 @@
   }
 
   public static abstract interface KeyStore.Entry {
+    method public default java.util.Set<java.security.KeyStore.Entry.Attribute> getAttributes();
+  }
+
+  public static abstract interface KeyStore.Entry.Attribute {
+    method public abstract java.lang.String getName();
+    method public abstract java.lang.String getValue();
   }
 
   public static abstract interface KeyStore.LoadStoreParameter {
@@ -58781,11 +58790,15 @@
 
   public static class KeyStore.PasswordProtection implements javax.security.auth.Destroyable java.security.KeyStore.ProtectionParameter {
     ctor public KeyStore.PasswordProtection(char[]);
+    ctor public KeyStore.PasswordProtection(char[], java.lang.String, java.security.spec.AlgorithmParameterSpec);
     method public synchronized char[] getPassword();
+    method public java.lang.String getProtectionAlgorithm();
+    method public java.security.spec.AlgorithmParameterSpec getProtectionParameters();
   }
 
   public static final class KeyStore.PrivateKeyEntry implements java.security.KeyStore.Entry {
     ctor public KeyStore.PrivateKeyEntry(java.security.PrivateKey, java.security.cert.Certificate[]);
+    ctor public KeyStore.PrivateKeyEntry(java.security.PrivateKey, java.security.cert.Certificate[], java.util.Set<java.security.KeyStore.Entry.Attribute>);
     method public java.security.cert.Certificate getCertificate();
     method public java.security.cert.Certificate[] getCertificateChain();
     method public java.security.PrivateKey getPrivateKey();
@@ -58796,11 +58809,13 @@
 
   public static final class KeyStore.SecretKeyEntry implements java.security.KeyStore.Entry {
     ctor public KeyStore.SecretKeyEntry(javax.crypto.SecretKey);
+    ctor public KeyStore.SecretKeyEntry(javax.crypto.SecretKey, java.util.Set<java.security.KeyStore.Entry.Attribute>);
     method public javax.crypto.SecretKey getSecretKey();
   }
 
   public static final class KeyStore.TrustedCertificateEntry implements java.security.KeyStore.Entry {
     ctor public KeyStore.TrustedCertificateEntry(java.security.cert.Certificate);
+    ctor public KeyStore.TrustedCertificateEntry(java.security.cert.Certificate, java.util.Set<java.security.KeyStore.Entry.Attribute>);
     method public java.security.cert.Certificate getTrustedCertificate();
   }
 
@@ -58936,10 +58951,11 @@
     method public abstract boolean equals(java.lang.Object);
     method public abstract java.lang.String getName();
     method public abstract int hashCode();
+    method public default boolean implies(javax.security.auth.Subject);
     method public abstract java.lang.String toString();
   }
 
-  public abstract interface PrivateKey implements java.security.Key {
+  public abstract interface PrivateKey implements javax.security.auth.Destroyable java.security.Key {
     field public static final long serialVersionUID = 6034044314589513430L; // 0x53bd3b559a12c6d6L
   }
 
@@ -59391,6 +59407,7 @@
     method public abstract java.lang.String toString();
     method public abstract void verify(java.security.PublicKey) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
     method public abstract void verify(java.security.PublicKey, java.lang.String) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
+    method public void verify(java.security.PublicKey, java.security.Provider) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.SignatureException;
     method protected java.lang.Object writeReplace() throws java.io.ObjectStreamException;
   }
 
@@ -59749,7 +59766,6 @@
     method public javax.security.auth.x500.X500Principal getSubjectX500Principal();
     method public abstract byte[] getTBSCertificate() throws java.security.cert.CertificateEncodingException;
     method public abstract int getVersion();
-    method public void verify(java.security.PublicKey, java.security.Provider) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.SignatureException;
   }
 
   public abstract interface X509Extension {
diff --git a/api/test-current.txt b/api/test-current.txt
index 1504416..f974393 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -50816,12 +50816,14 @@
     method public static java.lang.Class<?> forName(java.lang.String, boolean, java.lang.ClassLoader) throws java.lang.ClassNotFoundException;
     method public A getAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getAnnotations();
+    method public A[] getAnnotationsByType(java.lang.Class<A>);
     method public java.lang.String getCanonicalName();
     method public java.lang.ClassLoader getClassLoader();
     method public java.lang.Class<?>[] getClasses();
     method public java.lang.Class<?> getComponentType();
     method public java.lang.reflect.Constructor<T> getConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
     method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+    method public A getDeclaredAnnotation(java.lang.Class<A>);
     method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public java.lang.Class<?>[] getDeclaredClasses();
     method public java.lang.reflect.Constructor<T> getDeclaredConstructor(java.lang.Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
@@ -50865,6 +50867,7 @@
     method public boolean isPrimitive();
     method public boolean isSynthetic();
     method public T newInstance() throws java.lang.IllegalAccessException, java.lang.InstantiationException;
+    method public java.lang.String toGenericString();
   }
 
   public class ClassCastException extends java.lang.RuntimeException {
@@ -52263,7 +52266,6 @@
 
   public final class Field extends java.lang.reflect.AccessibleObject implements java.lang.reflect.Member {
     method public java.lang.Object get(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
-    method public A getAnnotation(java.lang.Class<A>);
     method public boolean getBoolean(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
     method public byte getByte(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
     method public char getChar(java.lang.Object) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException;
@@ -52295,7 +52297,7 @@
     method public abstract java.lang.reflect.Type getGenericComponentType();
   }
 
-  public abstract interface GenericDeclaration {
+  public abstract interface GenericDeclaration implements java.lang.reflect.AnnotatedElement {
     method public abstract java.lang.reflect.TypeVariable<?>[] getTypeParameters();
   }
 
@@ -52363,6 +52365,7 @@
     method public static boolean isTransient(int);
     method public static boolean isVolatile(int);
     method public static int methodModifiers();
+    method public static int parameterModifiers();
     method public static java.lang.String toString(int);
     field public static final int ABSTRACT = 1024; // 0x400
     field public static final int FINAL = 16; // 0x10
@@ -55336,6 +55339,12 @@
   }
 
   public static abstract interface KeyStore.Entry {
+    method public default java.util.Set<java.security.KeyStore.Entry.Attribute> getAttributes();
+  }
+
+  public static abstract interface KeyStore.Entry.Attribute {
+    method public abstract java.lang.String getName();
+    method public abstract java.lang.String getValue();
   }
 
   public static abstract interface KeyStore.LoadStoreParameter {
@@ -55344,11 +55353,15 @@
 
   public static class KeyStore.PasswordProtection implements javax.security.auth.Destroyable java.security.KeyStore.ProtectionParameter {
     ctor public KeyStore.PasswordProtection(char[]);
+    ctor public KeyStore.PasswordProtection(char[], java.lang.String, java.security.spec.AlgorithmParameterSpec);
     method public synchronized char[] getPassword();
+    method public java.lang.String getProtectionAlgorithm();
+    method public java.security.spec.AlgorithmParameterSpec getProtectionParameters();
   }
 
   public static final class KeyStore.PrivateKeyEntry implements java.security.KeyStore.Entry {
     ctor public KeyStore.PrivateKeyEntry(java.security.PrivateKey, java.security.cert.Certificate[]);
+    ctor public KeyStore.PrivateKeyEntry(java.security.PrivateKey, java.security.cert.Certificate[], java.util.Set<java.security.KeyStore.Entry.Attribute>);
     method public java.security.cert.Certificate getCertificate();
     method public java.security.cert.Certificate[] getCertificateChain();
     method public java.security.PrivateKey getPrivateKey();
@@ -55359,11 +55372,13 @@
 
   public static final class KeyStore.SecretKeyEntry implements java.security.KeyStore.Entry {
     ctor public KeyStore.SecretKeyEntry(javax.crypto.SecretKey);
+    ctor public KeyStore.SecretKeyEntry(javax.crypto.SecretKey, java.util.Set<java.security.KeyStore.Entry.Attribute>);
     method public javax.crypto.SecretKey getSecretKey();
   }
 
   public static final class KeyStore.TrustedCertificateEntry implements java.security.KeyStore.Entry {
     ctor public KeyStore.TrustedCertificateEntry(java.security.cert.Certificate);
+    ctor public KeyStore.TrustedCertificateEntry(java.security.cert.Certificate, java.util.Set<java.security.KeyStore.Entry.Attribute>);
     method public java.security.cert.Certificate getTrustedCertificate();
   }
 
@@ -55499,10 +55514,11 @@
     method public abstract boolean equals(java.lang.Object);
     method public abstract java.lang.String getName();
     method public abstract int hashCode();
+    method public default boolean implies(javax.security.auth.Subject);
     method public abstract java.lang.String toString();
   }
 
-  public abstract interface PrivateKey implements java.security.Key {
+  public abstract interface PrivateKey implements javax.security.auth.Destroyable java.security.Key {
     field public static final long serialVersionUID = 6034044314589513430L; // 0x53bd3b559a12c6d6L
   }
 
@@ -55954,6 +55970,7 @@
     method public abstract java.lang.String toString();
     method public abstract void verify(java.security.PublicKey) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
     method public abstract void verify(java.security.PublicKey, java.lang.String) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException, java.security.SignatureException;
+    method public void verify(java.security.PublicKey, java.security.Provider) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.SignatureException;
     method protected java.lang.Object writeReplace() throws java.io.ObjectStreamException;
   }
 
@@ -56312,7 +56329,6 @@
     method public javax.security.auth.x500.X500Principal getSubjectX500Principal();
     method public abstract byte[] getTBSCertificate() throws java.security.cert.CertificateEncodingException;
     method public abstract int getVersion();
-    method public void verify(java.security.PublicKey, java.security.Provider) throws java.security.cert.CertificateException, java.security.InvalidKeyException, java.security.NoSuchAlgorithmException, java.security.SignatureException;
   }
 
   public abstract interface X509Extension {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 851cf50..cfc4519 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -878,7 +878,7 @@
             = "android.app.action.DEVICE_POLICY_MANAGER_STATE_CHANGED";
 
     /**
-     * Broadcast action: sent when the device owner is set or changed.
+     * Broadcast action: sent when the device owner is set, changed or cleared.
      *
      * This broadcast is sent only to the primary user.
      * @see #ACTION_PROVISION_MANAGED_DEVICE
diff --git a/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java b/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java
index 17e533a..da815691 100644
--- a/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java
+++ b/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java
@@ -83,11 +83,6 @@
     }
 
     @Override
-    public void onMultiAdvertiseCallback(int status, boolean isStart,
-            AdvertiseSettings advertiseSettings) throws RemoteException {
-    }
-
-    @Override
     public void onConfigureMTU(String address, int mtu, int status) throws RemoteException {
     }
 
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 7498038..f4ebcaf 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -28,6 +28,7 @@
 
 import android.bluetooth.IBluetoothGattCallback;
 import android.bluetooth.IBluetoothGattServerCallback;
+import android.bluetooth.le.IAdvertiserCallback;
 
 /**
  * API for interacting with BLE / GATT
@@ -41,11 +42,15 @@
                    in String callingPackage);
     void stopScan(in int appIf, in boolean isServer);
     void flushPendingBatchResults(in int appIf, in boolean isServer);
-    void startMultiAdvertising(in int appIf,
+
+    void registerAdvertiser(in IAdvertiserCallback callback);
+    void unregisterAdvertiser(in int advertiserId);
+    void startMultiAdvertising(in int advertiserId,
                                in AdvertiseData advertiseData,
                                in AdvertiseData scanResponse,
                                in AdvertiseSettings settings);
-    void stopMultiAdvertising(in int appIf);
+    void stopMultiAdvertising(in int advertiserId);
+
     void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback);
     void unregisterClient(in int clientIf);
     void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport);
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
index 7163c37..efda08e 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -38,8 +38,6 @@
     void onDescriptorWrite(in String address, in int status, in int handle);
     void onNotify(in String address, in int handle, in byte[] value);
     void onReadRemoteRssi(in String address, in int rssi, in int status);
-    void onMultiAdvertiseCallback(in int status, boolean isStart,
-                                  in AdvertiseSettings advertiseSettings);
     void onScanManagerErrorCallback(in int errorCode);
     void onConfigureMTU(in String address, in int mtu, in int status);
     void onFoundOrLost(in boolean onFound, in ScanResult scanResult);
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index d468bd4..048f791 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -22,6 +22,7 @@
 import android.bluetooth.BluetoothUuid;
 import android.bluetooth.IBluetoothGatt;
 import android.bluetooth.IBluetoothManager;
+import android.bluetooth.le.IAdvertiserCallback;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.ParcelUuid;
@@ -162,7 +163,7 @@
     }
 
     /**
-     * Cleans up advertise clients. Should be called when bluetooth is down.
+     * Cleans up advertisers. Should be called when bluetooth is down.
      *
      * @hide
      */
@@ -228,7 +229,7 @@
     /**
      * Bluetooth GATT interface callbacks for advertising.
      */
-    private class AdvertiseCallbackWrapper extends BluetoothGattCallbackWrapper {
+    private class AdvertiseCallbackWrapper extends IAdvertiserCallback.Stub {
         private static final int LE_CALLBACK_TIMEOUT_MILLIS = 2000;
         private final AdvertiseCallback mAdvertiseCallback;
         private final AdvertiseData mAdvertisement;
@@ -236,10 +237,10 @@
         private final AdvertiseSettings mSettings;
         private final IBluetoothGatt mBluetoothGatt;
 
-        // mClientIf 0: not registered
+        // mAdvertiserId 0: not registered
         // -1: advertise stopped or registration timeout
         // >0: registered and advertising started
-        private int mClientIf;
+        private int mAdvertiserId;
         private boolean mIsAdvertising = false;
 
         public AdvertiseCallbackWrapper(AdvertiseCallback advertiseCallback,
@@ -251,35 +252,34 @@
             mScanResponse = scanResponse;
             mSettings = settings;
             mBluetoothGatt = bluetoothGatt;
-            mClientIf = 0;
+            mAdvertiserId = 0;
         }
 
         public void startRegisteration() {
             synchronized (this) {
-                if (mClientIf == -1) return;
+                if (mAdvertiserId == -1) return;
 
                 try {
-                    UUID uuid = UUID.randomUUID();
-                    mBluetoothGatt.registerClient(new ParcelUuid(uuid), this);
+                    mBluetoothGatt.registerAdvertiser(this);
                     wait(LE_CALLBACK_TIMEOUT_MILLIS);
                 } catch (InterruptedException | RemoteException e) {
                     Log.e(TAG, "Failed to start registeration", e);
                 }
-                if (mClientIf > 0 && mIsAdvertising) {
+                if (mAdvertiserId > 0 && mIsAdvertising) {
                     mLeAdvertisers.put(mAdvertiseCallback, this);
-                } else if (mClientIf <= 0) {
+                } else if (mAdvertiserId <= 0) {
 
                     // Registration timeout, reset mClientIf to -1 so no subsequent operations can
                     // proceed.
-                    if (mClientIf == 0) mClientIf = -1;
+                    if (mAdvertiserId == 0) mAdvertiserId = -1;
                     // Post internal error if registration failed.
                     postStartFailure(mAdvertiseCallback,
                             AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
                 } else {
                     // Unregister application if it's already registered but advertise failed.
                     try {
-                        mBluetoothGatt.unregisterClient(mClientIf);
-                        mClientIf = -1;
+                        mBluetoothGatt.unregisterAdvertiser(mAdvertiserId);
+                        mAdvertiserId = -1;
                     } catch (RemoteException e) {
                         Log.e(TAG, "remote exception when unregistering", e);
                     }
@@ -290,7 +290,7 @@
         public void stopAdvertising() {
             synchronized (this) {
                 try {
-                    mBluetoothGatt.stopMultiAdvertising(mClientIf);
+                    mBluetoothGatt.stopMultiAdvertising(mAdvertiserId);
                     wait(LE_CALLBACK_TIMEOUT_MILLIS);
                 } catch (InterruptedException | RemoteException e) {
                     Log.e(TAG, "Failed to stop advertising", e);
@@ -305,20 +305,20 @@
         }
 
         /**
-         * Application interface registered - app is ready to go
+         * Advertiser interface registered - app is ready to go
          */
         @Override
-        public void onClientRegistered(int status, int clientIf) {
-            Log.d(TAG, "onClientRegistered() - status=" + status + " clientIf=" + clientIf);
+        public void onAdvertiserRegistered(int status, int advertiserId) {
+            Log.d(TAG, "onAdvertiserRegistered() - status=" + status + " advertiserId=" + advertiserId);
             synchronized (this) {
                 if (status == BluetoothGatt.GATT_SUCCESS) {
                     try {
-                        if (mClientIf == -1) {
-                            // Registration succeeds after timeout, unregister client.
-                            mBluetoothGatt.unregisterClient(clientIf);
+                        if (mAdvertiserId == -1) {
+                            // Registration succeeds after timeout, unregister advertiser.
+                            mBluetoothGatt.unregisterAdvertiser(advertiserId);
                         } else {
-                            mClientIf = clientIf;
-                            mBluetoothGatt.startMultiAdvertising(mClientIf, mAdvertisement,
+                            mAdvertiserId = advertiserId;
+                            mBluetoothGatt.startMultiAdvertising(mAdvertiserId, mAdvertisement,
                                     mScanResponse, mSettings);
                         }
                         return;
@@ -327,7 +327,7 @@
                     }
                 }
                 // Registration failed.
-                mClientIf = -1;
+                mAdvertiserId = -1;
                 notifyAll();
             }
         }
@@ -346,10 +346,10 @@
                         postStartFailure(mAdvertiseCallback, status);
                     }
                 } else {
-                    // unregister client for stop.
+                    // unregister advertiser for stop.
                     try {
-                        mBluetoothGatt.unregisterClient(mClientIf);
-                        mClientIf = -1;
+                        mBluetoothGatt.unregisterAdvertiser(mAdvertiserId);
+                        mAdvertiserId = -1;
                         mIsAdvertising = false;
                         mLeAdvertisers.remove(mAdvertiseCallback);
                     } catch (RemoteException e) {
diff --git a/core/java/android/bluetooth/le/IAdvertiserCallback.aidl b/core/java/android/bluetooth/le/IAdvertiserCallback.aidl
new file mode 100644
index 0000000..c58b1df
--- /dev/null
+++ b/core/java/android/bluetooth/le/IAdvertiserCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.bluetooth.le;
+
+import android.bluetooth.le.AdvertiseSettings;
+
+/**
+ * Callback definitions for interacting with Advertiser
+ * @hide
+ */
+oneway interface IAdvertiserCallback {
+    void onAdvertiserRegistered(in int status, in int advertiserId);
+
+    void onMultiAdvertiseCallback(in int status, boolean isStart,
+                                  in AdvertiseSettings advertiseSettings);
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index d51559d..b295919 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2740,6 +2740,7 @@
             //@hide: SOUND_TRIGGER_SERVICE,
             SHORTCUT_SERVICE,
             //@hide: CONTEXTHUB_SERVICE,
+            SYSTEM_HEALTH_SERVICE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index f7743dd..19c82a5 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -165,6 +165,28 @@
         msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_LOAD_NANO_APP;
 
         long appId = app.getAppId();
+        // TODO(b/30808791): Remove this hack when the NanoApp API is fixed.
+        // Due to a bug in the NanoApp API, only the least significant four
+        // bytes of the app ID can be stored.  The most significant five
+        // bytes of a normal app ID are the "vendor", and thus the most
+        // significant of the bytes we have is the least significant byte
+        // of the vendor.  In the case that byte is the ASCII value for
+        // lower-case 'L', we assume the vendor is supposed to be "Googl"
+        // and fill in the four most significant bytes accordingly.
+        if ((appId >> 32) != 0) {
+            // We're unlikely to notice this warning, but at least
+            // we can avoid running our hack logic.
+            Log.w(TAG, "Code has not been updated since API fix.");
+        } else {
+            // Note: Lower-case 'L', not the number 1.
+            if (((appId >> 24) & 0xFF) == (long)'l') {
+                // Assume we're a Google nanoapp.
+                appId |= ((long)'G') << 56;
+                appId |= ((long)'o') << 48;
+                appId |= ((long)'o') << 40;
+                appId |= ((long)'g') << 32;
+            }
+        }
 
         msgHeader[HEADER_FIELD_LOAD_APP_ID_LO] = (int)(appId & 0xFFFFFFFF);
         msgHeader[HEADER_FIELD_LOAD_APP_ID_HI] = (int)((appId >> 32) & 0xFFFFFFFF);
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 54fea52..6f39935 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SystemApi;
 import android.os.ParcelFileDescriptor;
+import dalvik.system.CloseGuard;
 
 import java.io.FileDescriptor;
 
@@ -35,6 +36,8 @@
     // used by the JNI code
     private long mNativeContext;
 
+    private final CloseGuard mCloseGuard = CloseGuard.get();
+
     /**
      * UsbDevice should only be instantiated by UsbService implementation
      * @hide
@@ -44,7 +47,13 @@
     }
 
     /* package */ boolean open(String name, ParcelFileDescriptor pfd) {
-        return native_open(name, pfd.getFileDescriptor());
+        boolean wasOpened = native_open(name, pfd.getFileDescriptor());
+
+        if (wasOpened) {
+            mCloseGuard.open("close");
+        }
+
+        return wasOpened;
     }
 
     /**
@@ -54,7 +63,10 @@
      * to retrieve a new instance to reestablish communication with the device.
      */
     public void close() {
-        native_close();
+        if (mNativeContext != 0) {
+            native_close();
+            mCloseGuard.close();
+        }
     }
 
     /**
@@ -262,6 +274,16 @@
         }
     }
 
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            mCloseGuard.warnIfOpen();
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
     private native boolean native_open(String deviceName, FileDescriptor pfd);
     private native void native_close();
     private native int native_get_fd();
diff --git a/core/java/android/hardware/usb/UsbRequest.java b/core/java/android/hardware/usb/UsbRequest.java
index ce66084..6129119e 100644
--- a/core/java/android/hardware/usb/UsbRequest.java
+++ b/core/java/android/hardware/usb/UsbRequest.java
@@ -17,6 +17,7 @@
 package android.hardware.usb;
 
 import android.util.Log;
+import dalvik.system.CloseGuard;
 
 import java.nio.ByteBuffer;
 
@@ -48,6 +49,11 @@
     // for client use
     private Object mClientData;
 
+    // Prevent the connection from being finalized
+    private UsbDeviceConnection mConnection;
+
+    private final CloseGuard mCloseGuard = CloseGuard.get();
+
     public UsbRequest() {
     }
 
@@ -60,25 +66,35 @@
      */
     public boolean initialize(UsbDeviceConnection connection, UsbEndpoint endpoint) {
         mEndpoint = endpoint;
-        return native_init(connection, endpoint.getAddress(), endpoint.getAttributes(),
-                endpoint.getMaxPacketSize(), endpoint.getInterval());
+        mConnection = connection;
+
+        boolean wasInitialized = native_init(connection, endpoint.getAddress(),
+                endpoint.getAttributes(), endpoint.getMaxPacketSize(), endpoint.getInterval());
+
+        if (wasInitialized) {
+            mCloseGuard.open("close");
+        }
+
+        return wasInitialized;
     }
 
     /**
      * Releases all resources related to this request.
      */
     public void close() {
-        mEndpoint = null;
-        native_close();
+        if (mNativeContext != 0) {
+            mEndpoint = null;
+            mConnection = null;
+            native_close();
+            mCloseGuard.close();
+        }
     }
 
     @Override
     protected void finalize() throws Throwable {
         try {
-            if (mEndpoint != null) {
-                Log.v(TAG, "endpoint still open in finalize(): " + this);
-                close();
-            }
+            mCloseGuard.warnIfOpen();
+            close();
         } finally {
             super.finalize();
         }
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index b83fb26..0f0e9c4 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -516,13 +516,11 @@
                     Os.setsockoptLinger(fd, OsConstants.SOL_SOCKET, OsConstants.SO_LINGER, linger);
                     break;
                 case SocketOptions.SO_TIMEOUT:
-                    /*
-                     * SO_TIMEOUT from the core library gets converted to
-                     * SO_SNDTIMEO, but the option is supposed to set both
-                     * send and receive timeouts. Note: The incoming timeout
-                     * value is in milliseconds.
-                     */
+                    // The option must set both send and receive timeouts.
+                    // Note: The incoming timeout value is in milliseconds.
                     StructTimeval timeval = StructTimeval.fromMillis(intValue);
+                    Os.setsockoptTimeval(fd, OsConstants.SOL_SOCKET, OsConstants.SO_RCVTIMEO,
+                            timeval);
                     Os.setsockoptTimeval(fd, OsConstants.SOL_SOCKET, OsConstants.SO_SNDTIMEO,
                             timeval);
                     break;
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index fbd61cf3..c7c6ceb 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -284,8 +284,10 @@
 
         /**
          * The cached name associated with the phone number, if it exists.
-         * This value is not guaranteed to be current, if the contact information
-         * associated with this number has changed.
+         *
+         * <p>This value is typically filled in by the dialer app for the caching purpose,
+         * so it's not guaranteed to be present, and may not be current if the contact
+         * information associated with this number has changed.
          * <P>Type: TEXT</P>
          */
         public static final String CACHED_NAME = "name";
@@ -293,8 +295,10 @@
         /**
          * The cached number type (Home, Work, etc) associated with the
          * phone number, if it exists.
-         * This value is not guaranteed to be current, if the contact information
-         * associated with this number has changed.
+         *
+         * <p>This value is typically filled in by the dialer app for the caching purpose,
+         * so it's not guaranteed to be present, and may not be current if the contact
+         * information associated with this number has changed.
          * <P>Type: INTEGER</P>
          */
         public static final String CACHED_NUMBER_TYPE = "numbertype";
@@ -302,8 +306,10 @@
         /**
          * The cached number label, for a custom number type, associated with the
          * phone number, if it exists.
-         * This value is not guaranteed to be current, if the contact information
-         * associated with this number has changed.
+         *
+         * <p>This value is typically filled in by the dialer app for the caching purpose,
+         * so it's not guaranteed to be present, and may not be current if the contact
+         * information associated with this number has changed.
          * <P>Type: TEXT</P>
          */
         public static final String CACHED_NUMBER_LABEL = "numberlabel";
@@ -339,40 +345,50 @@
 
         /**
          * The cached URI to look up the contact associated with the phone number, if it exists.
-         * This value may not be current if the contact information associated with this number
-         * has changed.
+         *
+         * <p>This value is typically filled in by the dialer app for the caching purpose,
+         * so it's not guaranteed to be present, and may not be current if the contact
+         * information associated with this number has changed.
          * <P>Type: TEXT</P>
          */
         public static final String CACHED_LOOKUP_URI = "lookup_uri";
 
         /**
          * The cached phone number of the contact which matches this entry, if it exists.
-         * This value may not be current if the contact information associated with this number
-         * has changed.
+         *
+         * <p>This value is typically filled in by the dialer app for the caching purpose,
+         * so it's not guaranteed to be present, and may not be current if the contact
+         * information associated with this number has changed.
          * <P>Type: TEXT</P>
          */
         public static final String CACHED_MATCHED_NUMBER = "matched_number";
 
         /**
          * The cached normalized(E164) version of the phone number, if it exists.
-         * This value may not be current if the contact information associated with this number
-         * has changed.
+         *
+         * <p>This value is typically filled in by the dialer app for the caching purpose,
+         * so it's not guaranteed to be present, and may not be current if the contact
+         * information associated with this number has changed.
          * <P>Type: TEXT</P>
          */
         public static final String CACHED_NORMALIZED_NUMBER = "normalized_number";
 
         /**
          * The cached photo id of the picture associated with the phone number, if it exists.
-         * This value may not be current if the contact information associated with this number
-         * has changed.
+         *
+         * <p>This value is typically filled in by the dialer app for the caching purpose,
+         * so it's not guaranteed to be present, and may not be current if the contact
+         * information associated with this number has changed.
          * <P>Type: INTEGER (long)</P>
          */
         public static final String CACHED_PHOTO_ID = "photo_id";
 
         /**
          * The cached photo URI of the picture associated with the phone number, if it exists.
-         * This value may not be current if the contact information associated with this number
-         * has changed.
+         *
+         * <p>This value is typically filled in by the dialer app for the caching purpose,
+         * so it's not guaranteed to be present, and may not be current if the contact
+         * information associated with this number has changed.
          * <P>Type: TEXT (URI)</P>
          */
         public static final String CACHED_PHOTO_URI = "photo_uri";
@@ -380,9 +396,10 @@
         /**
          * The cached phone number, formatted with formatting rules based on the country the
          * user was in when the call was made or received.
-         * This value is not guaranteed to be present, and may not be current if the contact
-         * information associated with this number
-         * has changed.
+         *
+         * <p>This value is typically filled in by the dialer app for the caching purpose,
+         * so it's not guaranteed to be present, and may not be current if the contact
+         * information associated with this number has changed.
          * <P>Type: TEXT</P>
          */
         public static final String CACHED_FORMATTED_NUMBER = "formatted_number";
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index c70304e..c495e6c 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -35,6 +35,7 @@
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.database.Cursor;
+import android.database.CursorWrapper;
 import android.database.DatabaseUtils;
 import android.graphics.Rect;
 import android.net.Uri;
@@ -138,8 +139,20 @@
     public static final String DIRECTORY_PARAM_KEY = "directory";
 
     /**
-     * A query parameter that limits the number of results returned. The
+     * A query parameter that limits the number of results returned for supported URIs. The
      * parameter value should be an integer.
+     *
+     * <p>This parameter is not supported by all URIs.  Supported URIs include, but not limited to,
+     * {@link Contacts#CONTENT_URI},
+     * {@link RawContacts#CONTENT_URI},
+     * {@link Data#CONTENT_URI},
+     * {@link CommonDataKinds.Phone#CONTENT_URI},
+     * {@link CommonDataKinds.Callable#CONTENT_URI},
+     * {@link CommonDataKinds.Email#CONTENT_URI},
+     * {@link CommonDataKinds.Contactables#CONTENT_URI},
+     *
+     * <p>In order to limit the number of rows returned by a non-supported URI, you can implement a
+     * {@link CursorWrapper} and override the {@link CursorWrapper#getCount()} methods.
      */
     public static final String LIMIT_PARAM_KEY = "limit";
 
@@ -437,6 +450,9 @@
 
         /**
          * _ID of the default directory, which represents locally stored contacts.
+         * <b>This is only supported by {@link ContactsContract.Contacts#CONTENT_URI} and
+         * {@link ContactsContract.Contacts#CONTENT_FILTER_URI}.
+         * Other URLs do not support the concept of "visible" or "invisible" contacts.
          */
         public static final long DEFAULT = 0;
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2c7626c..b05f3c2 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6399,6 +6399,13 @@
                 = "demo_user_setup_complete";
 
         /**
+         * Specifies whether the web action API is enabled.
+         *
+         * @hide
+         */
+        public static final String WEB_ACTION_ENABLED = "web_action_enabled";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -7484,27 +7491,41 @@
         public static final String WEBVIEW_DATA_REDUCTION_PROXY_KEY =
                 "webview_data_reduction_proxy_key";
 
-        /**
-         * Whether or not the WebView fallback mechanism should be enabled.
-         * 0=disabled, 1=enabled.
-         * @hide
-         */
-        public static final String WEBVIEW_FALLBACK_LOGIC_ENABLED =
-                "webview_fallback_logic_enabled";
+       /**
+        * Whether or not the WebView fallback mechanism should be enabled.
+        * 0=disabled, 1=enabled.
+        * @hide
+        */
+       public static final String WEBVIEW_FALLBACK_LOGIC_ENABLED =
+               "webview_fallback_logic_enabled";
 
-        /**
-         * Name of the package used as WebView provider (if unset the provider is instead determined
-         * by the system).
-         * @hide
-         */
-        public static final String WEBVIEW_PROVIDER = "webview_provider";
+       /**
+        * Name of the package used as WebView provider (if unset the provider is instead determined
+        * by the system).
+        * @hide
+        */
+       public static final String WEBVIEW_PROVIDER = "webview_provider";
 
-        /**
-         * Developer setting to enable WebView multiprocess rendering.
-         * @hide
-         */
-        @SystemApi
-        public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
+       /**
+        * Developer setting to enable WebView multiprocess rendering.
+        * @hide
+        */
+       @SystemApi
+       public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
+
+       /**
+        * The maximum number of notifications shown in 24 hours when switching networks.
+        * @hide
+        */
+       public static final String NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT =
+              "network_switch_notification_daily_limit";
+
+       /**
+        * The minimum time in milliseconds between notifications when switching networks.
+        * @hide
+        */
+       public static final String NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS =
+              "network_switch_notification_rate_limit_millis";
 
        /**
         * Whether Wifi display is enabled/disabled
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index 080dd07..ccaf204 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -58,7 +58,7 @@
     private final int mOwnerPid;
     private final boolean mClientWritable;
     private final long mMemoryAddr;
-    private ParcelFileDescriptor mFd;
+    private int mFd;
 
     /**
      * Creates a new instance.
@@ -75,23 +75,24 @@
         mOwnerPid = Process.myPid();
         mClientWritable = clientWritable;
         final String name = UUID.randomUUID().toString();
-        mFd = ParcelFileDescriptor.adoptFd(nativeCreate(name, size));
-        mMemoryAddr = nativeOpen(mFd.getFd(), true, clientWritable);
+        mFd = nativeCreate(name, size);
+        mMemoryAddr = nativeOpen(mFd, true, clientWritable);
         mCloseGuard.open("close");
     }
 
     private MemoryIntArray(Parcel parcel) throws IOException {
         mOwnerPid = parcel.readInt();
         mClientWritable = (parcel.readInt() == 1);
-        mFd = parcel.readParcelable(null);
-        if (mFd == null) {
+        ParcelFileDescriptor pfd = parcel.readParcelable(null);
+        if (pfd == null) {
             throw new IOException("No backing file descriptor");
         }
+        mFd = pfd.detachFd();
         final long memoryAddress = parcel.readLong();
         if (isOwner()) {
             mMemoryAddr = memoryAddress;
         } else {
-            mMemoryAddr = nativeOpen(mFd.getFd(), false, mClientWritable);
+            mMemoryAddr = nativeOpen(mFd, false, mClientWritable);
         }
         mCloseGuard.open("close");
     }
@@ -114,7 +115,7 @@
     public int get(int index) throws IOException {
         enforceNotClosed();
         enforceValidIndex(index);
-        return nativeGet(mFd.getFd(), mMemoryAddr, index, isOwner());
+        return nativeGet(mFd, mMemoryAddr, index, isOwner());
     }
 
     /**
@@ -130,7 +131,7 @@
         enforceNotClosed();
         enforceWritable();
         enforceValidIndex(index);
-        nativeSet(mFd.getFd(), mMemoryAddr, index, value, isOwner());
+        nativeSet(mFd, mMemoryAddr, index, value, isOwner());
     }
 
     /**
@@ -140,7 +141,7 @@
      */
     public int size() throws IOException {
         enforceNotClosed();
-        return nativeSize(mFd.getFd());
+        return nativeSize(mFd);
     }
 
     /**
@@ -151,9 +152,8 @@
     @Override
     public void close() throws IOException {
         if (!isClosed()) {
-            ParcelFileDescriptor pfd = mFd;
-            mFd = null;
-            nativeClose(pfd.getFd(), mMemoryAddr, isOwner());
+            nativeClose(mFd, mMemoryAddr, isOwner());
+            mFd = -1;
             mCloseGuard.close();
         }
     }
@@ -162,7 +162,7 @@
      * @return Whether this array is closed and shouldn't be used.
      */
     public boolean isClosed() {
-        return mFd == null;
+        return mFd == -1;
     }
 
     @Override
@@ -182,11 +182,16 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeInt(mOwnerPid);
-        parcel.writeInt(mClientWritable ? 1 : 0);
-        // Don't let writing to a parcel to close our fd - plz
-        parcel.writeParcelable(mFd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-        parcel.writeLong(mMemoryAddr);
+        ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(mFd);
+        try {
+            parcel.writeInt(mOwnerPid);
+            parcel.writeInt(mClientWritable ? 1 : 0);
+            // Don't let writing to a parcel to close our fd - plz
+            parcel.writeParcelable(pfd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+            parcel.writeLong(mMemoryAddr);
+        } finally {
+            pfd.detachFd();
+        }
     }
 
     @Override
@@ -201,19 +206,12 @@
             return false;
         }
         MemoryIntArray other = (MemoryIntArray) obj;
-        if (mFd == null) {
-            if (other.mFd != null) {
-                return false;
-            }
-        } else if (mFd.getFd() != other.mFd.getFd()) {
-            return false;
-        }
-        return true;
+        return mFd == other.mFd;
     }
 
     @Override
     public int hashCode() {
-        return mFd != null ? mFd.hashCode() : 1;
+        return mFd;
     }
 
     private boolean isOwner() {
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 286e097..f92d83a 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -96,6 +96,8 @@
 
     private HwuiContext mHwuiContext;
 
+    private boolean mIsSingleBuffered;
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SCALING_MODE_FREEZE, SCALING_MODE_SCALE_TO_WINDOW,
@@ -158,7 +160,7 @@
         if (surfaceTexture == null) {
             throw new IllegalArgumentException("surfaceTexture must not be null");
         }
-
+        mIsSingleBuffered = surfaceTexture.isSingleBuffered();
         synchronized (mLock) {
             mName = surfaceTexture.toString();
             setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
@@ -457,7 +459,10 @@
             // create a new native Surface and return it after reducing
             // the reference count on mNativeObject.  Either way, it is
             // not necessary to call nativeRelease() here.
+            // NOTE: This must be kept synchronized with the native parceling code
+            // in frameworks/native/libs/Surface.cpp
             mName = source.readString();
+            mIsSingleBuffered = source.readInt() != 0;
             setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
         }
     }
@@ -468,7 +473,10 @@
             throw new IllegalArgumentException("dest must not be null");
         }
         synchronized (mLock) {
+            // NOTE: This must be kept synchronized with the native parceling code
+            // in frameworks/native/libs/Surface.cpp
             dest.writeString(mName);
+            dest.writeInt(mIsSingleBuffered ? 1 : 0);
             nativeWriteToParcel(mNativeObject, dest);
         }
         if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
@@ -531,6 +539,14 @@
     }
 
     /**
+     * Returns whether or not this Surface is backed by a single-buffered SurfaceTexture
+     * @hide
+     */
+    public boolean isSingleBuffered() {
+        return mIsSingleBuffered;
+    }
+
+    /**
      * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or
      * when a SurfaceTexture could not successfully be allocated.
      */
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 7e19562..36b4b06 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -228,6 +228,7 @@
      */
     @Override
     protected void destroyHardwareResources() {
+        super.destroyHardwareResources();
         destroyHardwareLayer();
     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9b2075e..aa17e80 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10391,7 +10391,7 @@
      *                  ancestors or by window visibility
      * @return true if this view is visible to the user, not counting clipping or overlapping
      */
-    @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) {
+    boolean dispatchVisibilityAggregated(boolean isVisible) {
         final boolean thisVisible = getVisibility() == VISIBLE;
         // If we're not visible but something is telling us we are, ignore it.
         if (thisVisible || !isVisible) {
@@ -15534,7 +15534,7 @@
         if (vis != GONE) {
             onWindowVisibilityChanged(vis);
             if (isShown()) {
-                // Calling onVisibilityChanged directly here since the subtree will also
+                // Calling onVisibilityAggregated directly here since the subtree will also
                 // receive dispatchAttachedToWindow and this same call
                 onVisibilityAggregated(vis == VISIBLE);
             }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index d0c9234..d786eaf 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -52,7 +52,6 @@
 import android.media.AudioManager;
 import android.os.Binder;
 import android.os.Build;
-import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Handler;
@@ -1468,6 +1467,8 @@
         final int viewVisibility = getHostVisibility();
         final boolean viewVisibilityChanged = !mFirst
                 && (mViewVisibility != viewVisibility || mNewSurfaceNeeded);
+        final boolean viewUserVisibilityChanged = !mFirst &&
+                ((mViewVisibility == View.VISIBLE) != (viewVisibility == View.VISIBLE));
 
         WindowManager.LayoutParams params = null;
         if (mWindowAttributesChanged) {
@@ -1541,13 +1542,7 @@
         if (viewVisibilityChanged) {
             mAttachInfo.mWindowVisibility = viewVisibility;
             host.dispatchWindowVisibilityChanged(viewVisibility);
-
-            // Prior to N we didn't have dispatchVisibilityAggregated to give a more accurate
-            // view into when views are visible to the user or not. ImageView never dealt with
-            // telling its drawable about window visibility, among other things. Some apps cause
-            // an additional crossfade animation when windows become visible if they get this
-            // additional call, so only send it to new apps to avoid new visual jank.
-            if (host.getContext().getApplicationInfo().targetSdkVersion >= VERSION_CODES.N) {
+            if (viewUserVisibilityChanged) {
                 host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
             }
             if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 0b9f9d0..2a524ec 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -507,6 +507,11 @@
          * Retrieves the {@param outBounds} from the stack with id {@param stackId}.
          */
         void getStackBounds(int stackId, Rect outBounds);
+
+        /**
+         * Overrides all currently playing app animations with {@param a}.
+         */
+        void overridePlayingAppAnimationsLw(Animation a);
     }
 
     public interface PointerEventListener {
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index 28e31c4..ee5bbe8 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -23,14 +23,18 @@
 import android.util.LongSparseArray;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.List;
 
 /**
  * Cache for AccessibilityWindowInfos and AccessibilityNodeInfos.
  * It is updated when windows change or nodes change.
+ * @hide
  */
-final class AccessibilityCache {
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public final class AccessibilityCache {
 
     private static final String LOG_TAG = "AccessibilityCache";
 
@@ -40,6 +44,8 @@
 
     private final Object mLock = new Object();
 
+    private final AccessibilityNodeRefresher mAccessibilityNodeRefresher;
+
     private long mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
     private long mInputFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
 
@@ -54,6 +60,10 @@
     private final SparseArray<AccessibilityWindowInfo> mTempWindowArray =
             new SparseArray<>();
 
+    public AccessibilityCache(AccessibilityNodeRefresher nodeRefresher) {
+        mAccessibilityNodeRefresher = nodeRefresher;
+    }
+
     public void setWindows(List<AccessibilityWindowInfo> windows) {
         synchronized (mLock) {
             if (DEBUG) {
@@ -170,7 +180,7 @@
             return;
         }
         // The node changed so we will just refresh it right now.
-        if (cachedInfo.refresh(true)) {
+        if (mAccessibilityNodeRefresher.refreshNode(cachedInfo, true)) {
             return;
         }
         // Weird, we could not refresh. Just evict the entire sub-tree.
@@ -285,10 +295,12 @@
 
                 // Also be careful if the parent has changed since the new
                 // parent may be a predecessor of the old parent which will
-                // add cyclse to the cache.
+                // add cycles to the cache.
                 final long oldParentId = oldInfo.getParentNodeId();
                 if (info.getParentNodeId() != oldParentId) {
                     clearSubTreeLocked(windowId, oldParentId);
+                } else {
+                    oldInfo.recycle();
                 }
            }
 
@@ -296,6 +308,12 @@
             // will wipe the data of the cached info.
             AccessibilityNodeInfo clone = AccessibilityNodeInfo.obtain(info);
             nodes.put(sourceId, clone);
+            if (clone.isAccessibilityFocused()) {
+                mAccessibilityFocus = sourceId;
+            }
+            if (clone.isFocused()) {
+                mInputFocus = sourceId;
+            }
         }
     }
 
@@ -383,6 +401,7 @@
             final long childNodeId = current.getChildId(i);
             clearSubTreeRecursiveLocked(nodes, childNodeId);
         }
+        current.recycle();
     }
 
     /**
@@ -505,4 +524,11 @@
             }
         }
     }
+
+    // Layer of indirection included to break dependency chain for testing
+    public static class AccessibilityNodeRefresher {
+        public boolean refreshNode(AccessibilityNodeInfo info, boolean bypassCache) {
+            return info.refresh(bypassCache);
+        }
+    }
 }
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 1406fbd..1543597 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -104,7 +104,7 @@
         new SparseArray<>();
 
     private static final AccessibilityCache sAccessibilityCache =
-        new AccessibilityCache();
+        new AccessibilityCache(new AccessibilityCache.AccessibilityNodeRefresher());
 
     /**
      * @return The client for the current thread.
@@ -293,6 +293,9 @@
                             interactionId);
                     finalizeAndCacheAccessibilityNodeInfos(infos, connectionId);
                     if (infos != null && !infos.isEmpty()) {
+                        for (int i = 1; i < infos.size(); i++) {
+                            infos.get(i).recycle();
+                        }
                         return infos.get(0);
                     }
                 }
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 7880b1a..d382ca7 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -35,6 +35,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * This class represents a node of the window content as well as actions that
@@ -553,6 +554,8 @@
      */
     private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;
 
+    private static final AtomicInteger sNumInstancesInUse = new AtomicInteger();
+
     /**
      * Gets the accessibility view id which identifies a View in the view three.
      *
@@ -2688,6 +2691,7 @@
      */
     public static AccessibilityNodeInfo obtain() {
         AccessibilityNodeInfo info = sPool.acquire();
+        sNumInstancesInUse.incrementAndGet();
         return (info != null) ? info : new AccessibilityNodeInfo();
     }
 
@@ -2715,6 +2719,16 @@
     public void recycle() {
         clear();
         sPool.release(this);
+        sNumInstancesInUse.decrementAndGet();
+    }
+
+    /**
+     * @return The number of instances of this class that have been obtained but not recycled.
+     *
+     * @hide
+     */
+    public static int getNumInstancesInUse() {
+        return sNumInstancesInUse.get();
     }
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index 52f35de..8e308d6 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -23,6 +23,8 @@
 import android.util.LongArray;
 import android.util.Pools.SynchronizedPool;
 
+import java.util.concurrent.atomic.AtomicInteger;
+
 /**
  * This class represents a state snapshot of a window for accessibility
  * purposes. The screen content contains one or more windows where some
@@ -81,6 +83,7 @@
     private static final int MAX_POOL_SIZE = 10;
     private static final SynchronizedPool<AccessibilityWindowInfo> sPool =
             new SynchronizedPool<AccessibilityWindowInfo>(MAX_POOL_SIZE);
+    private static final AtomicInteger sNumInstancesInUse = new AtomicInteger();
 
     // Data.
     private int mType = UNDEFINED;
@@ -400,6 +403,7 @@
         if (info == null) {
             info = new AccessibilityWindowInfo();
         }
+        sNumInstancesInUse.incrementAndGet();
         return info;
     }
 
@@ -437,6 +441,15 @@
     }
 
     /**
+     * @return The number of instances of this class that have been obtained but not recycled.
+     *
+     * @hide
+     */
+    public static int getNumInstancesInUse() {
+        return sNumInstancesInUse.get();
+    }
+
+    /**
      * Return an instance back to be reused.
      * <p>
      * <strong>Note:</strong> You must not touch the object after calling this function.
@@ -447,6 +460,7 @@
     public void recycle() {
         clear();
         sPool.release(this);
+        sNumInstancesInUse.decrementAndGet();
     }
 
     @Override
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index d9d319a..119b8ed 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -617,6 +617,8 @@
     private int mTouchSlop;
     private float mDensityScale;
 
+    private float mScrollFactor;
+
     private InputConnection mDefInputConnection;
     private InputConnectionWrapper mPublicInputConnection;
 
@@ -874,6 +876,7 @@
 
         final ViewConfiguration configuration = ViewConfiguration.get(mContext);
         mTouchSlop = configuration.getScaledTouchSlop();
+        mScrollFactor = configuration.getScaledScrollFactor();
         mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
         mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
         mOverscrollDistance = configuration.getScaledOverscrollDistance();
@@ -4207,21 +4210,26 @@
 
     @Override
     public boolean onGenericMotionEvent(MotionEvent event) {
-        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
-            switch (event.getAction()) {
-                case MotionEvent.ACTION_SCROLL:
-                    if (mTouchMode == TOUCH_MODE_REST) {
-                        final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
-                        if (vscroll != 0) {
-                            final int delta = (int) (vscroll * getVerticalScrollFactor());
-                            if (!trackMotionScroll(delta, delta)) {
-                                return true;
-                            }
-                        }
-                    }
-                    break;
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_SCROLL:
+                final float axisValue;
+                if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
+                    axisValue = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                } else if (event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER)) {
+                    axisValue = event.getAxisValue(MotionEvent.AXIS_SCROLL);
+                } else {
+                    axisValue = 0;
+                }
 
-                case MotionEvent.ACTION_BUTTON_PRESS:
+                final int delta = Math.round(axisValue * mScrollFactor);
+                if (delta != 0) {
+                    if (!trackMotionScroll(delta, delta)) {
+                        return true;
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_BUTTON_PRESS:
+                if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
                     int actionButton = event.getActionButton();
                     if ((actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
                             || actionButton == MotionEvent.BUTTON_SECONDARY)
@@ -4231,8 +4239,8 @@
                             removeCallbacks(mPendingCheckForTap);
                         }
                     }
-                    break;
-            }
+                }
+                break;
         }
 
         return super.onGenericMotionEvent(event);
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 5eea7a4..918b6c0 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -129,6 +129,8 @@
     private int mOverscrollDistance;
     private int mOverflingDistance;
 
+    private float mScrollFactor;
+
     /**
      * ID of the active pointer. This is used to retain consistency during
      * drags/flings if multiple pointers are used.
@@ -222,6 +224,7 @@
         mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
         mOverscrollDistance = configuration.getScaledOverscrollDistance();
         mOverflingDistance = configuration.getScaledOverflingDistance();
+        mScrollFactor = configuration.getScaledScrollFactor();
     }
 
     @Override
@@ -724,30 +727,35 @@
 
     @Override
     public boolean onGenericMotionEvent(MotionEvent event) {
-        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
-            switch (event.getAction()) {
-                case MotionEvent.ACTION_SCROLL: {
-                    if (!mIsBeingDragged) {
-                        final float hscroll;
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_SCROLL: {
+                if (!mIsBeingDragged) {
+                    final float axisValue;
+                    if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
                         if ((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) {
-                            hscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                            axisValue = -event.getAxisValue(MotionEvent.AXIS_VSCROLL);
                         } else {
-                            hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
+                            axisValue = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
                         }
-                        if (hscroll != 0) {
-                            final int delta = (int) (hscroll * getHorizontalScrollFactor());
-                            final int range = getScrollRange();
-                            int oldScrollX = mScrollX;
-                            int newScrollX = oldScrollX + delta;
-                            if (newScrollX < 0) {
-                                newScrollX = 0;
-                            } else if (newScrollX > range) {
-                                newScrollX = range;
-                            }
-                            if (newScrollX != oldScrollX) {
-                                super.scrollTo(newScrollX, mScrollY);
-                                return true;
-                            }
+                    } else if (event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER)) {
+                        axisValue = event.getAxisValue(MotionEvent.AXIS_SCROLL);
+                    } else {
+                        axisValue = 0;
+                    }
+
+                    final int delta = Math.round(axisValue * mScrollFactor);
+                    if (delta != 0) {
+                        final int range = getScrollRange();
+                        int oldScrollX = mScrollX;
+                        int newScrollX = oldScrollX + delta;
+                        if (newScrollX < 0) {
+                            newScrollX = 0;
+                        } else if (newScrollX > range) {
+                            newScrollX = range;
+                        }
+                        if (newScrollX != oldScrollX) {
+                            super.scrollTo(newScrollX, mScrollY);
+                            return true;
                         }
                     }
                 }
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index ea0afb9..aa67c82 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -22,7 +22,6 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.ColorStateList;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -115,11 +114,17 @@
     private int mBaseline = -1;
     private boolean mBaselineAlignBottom = false;
 
-    // AdjustViewBounds behavior will be in compatibility mode for older apps.
-    private boolean mAdjustViewBoundsCompat = false;
+    /** Compatibility modes dependent on targetSdkVersion of the app. */
+    private static boolean sCompatDone;
+
+    /** AdjustViewBounds behavior will be in compatibility mode for older apps. */
+    private static boolean sCompatAdjustViewBounds;
 
     /** Whether to pass Resources when creating the source from a stream. */
-    private boolean mUseCorrectStreamDensity;
+    private static boolean sCompatUseCorrectStreamDensity;
+
+    /** Whether to use pre-Nougat drawable visibility dispatching conditions. */
+    private static boolean sCompatDrawableVisibilityDispatch;
 
     private static final ScaleType[] sScaleTypeArray = {
         ScaleType.MATRIX,
@@ -206,9 +211,13 @@
         mMatrix = new Matrix();
         mScaleType = ScaleType.FIT_CENTER;
 
-        final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
-        mAdjustViewBoundsCompat = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
-        mUseCorrectStreamDensity = targetSdkVersion > Build.VERSION_CODES.M;
+        if (!sCompatDone) {
+            final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+            sCompatAdjustViewBounds = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
+            sCompatUseCorrectStreamDensity = targetSdkVersion > Build.VERSION_CODES.M;
+            sCompatDrawableVisibilityDispatch = targetSdkVersion < Build.VERSION_CODES.N;
+            sCompatDone = true;
+        }
     }
 
     @Override
@@ -881,8 +890,8 @@
             InputStream stream = null;
             try {
                 stream = mContext.getContentResolver().openInputStream(uri);
-                return Drawable.createFromResourceStream(
-                        mUseCorrectStreamDensity ? getResources() : null, null, stream, null);
+                return Drawable.createFromResourceStream(sCompatUseCorrectStreamDensity
+                        ? getResources() : null, null, stream, null);
             } catch (Exception e) {
                 Log.w(LOG_TAG, "Unable to open content: " + uri, e);
             } finally {
@@ -917,10 +926,13 @@
             mRecycleableBitmapDrawable.setBitmap(null);
         }
 
+        boolean sameDrawable = false;
+
         if (mDrawable != null) {
+            sameDrawable = mDrawable == d;
             mDrawable.setCallback(null);
             unscheduleDrawable(mDrawable);
-            if (isAttachedToWindow()) {
+            if (!sCompatDrawableVisibilityDispatch && !sameDrawable && isAttachedToWindow()) {
                 mDrawable.setVisible(false, false);
             }
         }
@@ -933,8 +945,12 @@
             if (d.isStateful()) {
                 d.setState(getDrawableState());
             }
-            d.setVisible(isAttachedToWindow() && getWindowVisibility() == VISIBLE && isShown(),
-                    true);
+            if (!sameDrawable || sCompatDrawableVisibilityDispatch) {
+                final boolean visible = sCompatDrawableVisibilityDispatch
+                        ? getVisibility() == VISIBLE
+                        : isAttachedToWindow() && getWindowVisibility() == VISIBLE && isShown();
+                d.setVisible(visible, true);
+            }
             d.setLevel(mLevel);
             mDrawableWidth = d.getIntrinsicWidth();
             mDrawableHeight = d.getIntrinsicHeight();
@@ -1057,7 +1073,7 @@
                                 pleft + pright;
 
                         // Allow the width to outgrow its original estimate if height is fixed.
-                        if (!resizeHeight && !mAdjustViewBoundsCompat) {
+                        if (!resizeHeight && !sCompatAdjustViewBounds) {
                             widthSize = resolveAdjustedSize(newWidth, mMaxWidth, widthMeasureSpec);
                         }
 
@@ -1073,7 +1089,7 @@
                                 ptop + pbottom;
 
                         // Allow the height to outgrow its original estimate if width is fixed.
-                        if (!resizeWidth && !mAdjustViewBoundsCompat) {
+                        if (!resizeWidth && !sCompatAdjustViewBounds) {
                             heightSize = resolveAdjustedSize(newHeight, mMaxHeight,
                                     heightMeasureSpec);
                         }
@@ -1512,11 +1528,40 @@
     @Override
     public void onVisibilityAggregated(boolean isVisible) {
         super.onVisibilityAggregated(isVisible);
-        if (mDrawable != null) {
+        // Only do this for new apps post-Nougat
+        if (mDrawable != null && !sCompatDrawableVisibilityDispatch) {
             mDrawable.setVisible(isVisible, false);
         }
     }
 
+    @RemotableViewMethod
+    @Override
+    public void setVisibility(int visibility) {
+        super.setVisibility(visibility);
+        // Only do this for old apps pre-Nougat; new apps use onVisibilityAggregated
+        if (mDrawable != null && sCompatDrawableVisibilityDispatch) {
+            mDrawable.setVisible(visibility == VISIBLE, false);
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        // Only do this for old apps pre-Nougat; new apps use onVisibilityAggregated
+        if (mDrawable != null && sCompatDrawableVisibilityDispatch) {
+            mDrawable.setVisible(getVisibility() == VISIBLE, false);
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        // Only do this for old apps pre-Nougat; new apps use onVisibilityAggregated
+        if (mDrawable != null && sCompatDrawableVisibilityDispatch) {
+            mDrawable.setVisible(false, false);
+        }
+    }
+
     @Override
     public CharSequence getAccessibilityClassName() {
         return ImageView.class.getName();
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 167d526..c92ee15 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -193,6 +193,8 @@
 
     private int mAnimationStyle = ANIMATION_STYLE_DEFAULT;
 
+    private int mGravity = Gravity.NO_GRAVITY;
+
     private static final int[] ABOVE_ANCHOR_STATE_SET = new int[] {
         com.android.internal.R.attr.state_above_anchor
     };
@@ -1141,15 +1143,11 @@
 
         mIsShowing = true;
         mIsDropdown = false;
+        mGravity = gravity;
 
         final WindowManager.LayoutParams p = createPopupLayoutParams(token);
         preparePopup(p);
 
-        // Only override the default if some gravity was specified.
-        if (gravity != Gravity.NO_GRAVITY) {
-            p.gravity = gravity;
-        }
-
         p.x = x;
         p.y = y;
 
@@ -1394,8 +1392,8 @@
     }
 
     private int computeGravity() {
-        int gravity = Gravity.START | Gravity.TOP;
-        if (mClipToScreen || mClippingEnabled) {
+        int gravity = mGravity == Gravity.NO_GRAVITY ?  Gravity.START | Gravity.TOP : mGravity;
+        if (mIsDropdown && (mClipToScreen || mClippingEnabled)) {
             gravity |= Gravity.DISPLAY_CLIP_VERTICAL;
         }
         return gravity;
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 493b28c..e696ff7 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -135,6 +135,8 @@
     private int mOverscrollDistance;
     private int mOverflingDistance;
 
+    private int mScrollFactor;
+
     /**
      * ID of the active pointer. This is used to retain consistency during
      * drags/flings if multiple pointers are used.
@@ -248,6 +250,7 @@
         mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
         mOverscrollDistance = configuration.getScaledOverscrollDistance();
         mOverflingDistance = configuration.getScaledOverflingDistance();
+        mScrollFactor = configuration.getScaledScrollFactor();
     }
 
     @Override
@@ -782,30 +785,35 @@
 
     @Override
     public boolean onGenericMotionEvent(MotionEvent event) {
-        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
-            switch (event.getAction()) {
-                case MotionEvent.ACTION_SCROLL: {
-                    if (!mIsBeingDragged) {
-                        final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
-                        if (vscroll != 0) {
-                            final int delta = (int) (vscroll * getVerticalScrollFactor());
-                            final int range = getScrollRange();
-                            int oldScrollY = mScrollY;
-                            int newScrollY = oldScrollY - delta;
-                            if (newScrollY < 0) {
-                                newScrollY = 0;
-                            } else if (newScrollY > range) {
-                                newScrollY = range;
-                            }
-                            if (newScrollY != oldScrollY) {
-                                super.scrollTo(mScrollX, newScrollY);
-                                return true;
-                            }
-                        }
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_SCROLL:
+                final float axisValue;
+                if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
+                    axisValue = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                } else if (event.isFromSource(InputDevice.SOURCE_ROTARY_ENCODER)) {
+                    axisValue = event.getAxisValue(MotionEvent.AXIS_SCROLL);
+                } else {
+                    axisValue = 0;
+                }
+
+                final int delta = Math.round(axisValue * mScrollFactor);
+                if (delta != 0) {
+                    final int range = getScrollRange();
+                    int oldScrollY = mScrollY;
+                    int newScrollY = oldScrollY - delta;
+                    if (newScrollY < 0) {
+                        newScrollY = 0;
+                    } else if (newScrollY > range) {
+                        newScrollY = range;
+                    }
+                    if (newScrollY != oldScrollY) {
+                        super.scrollTo(mScrollX, newScrollY);
+                        return true;
                     }
                 }
-            }
+                break;
         }
+
         return super.onGenericMotionEvent(event);
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 64779a2..ce6400e9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1310,6 +1310,10 @@
             createEditorIfNeeded();
             mEditor.mKeyListener = TextKeyListener.getInstance(autotext, cap);
             mEditor.mInputType = inputType;
+        } else if (editable) {
+            createEditorIfNeeded();
+            mEditor.mKeyListener = TextKeyListener.getInstance();
+            mEditor.mInputType = EditorInfo.TYPE_CLASS_TEXT;
         } else if (isTextSelectable()) {
             // Prevent text changes from keyboard.
             if (mEditor != null) {
@@ -1319,10 +1323,6 @@
             bufferType = BufferType.SPANNABLE;
             // So that selection can be changed using arrow keys and touch is handled.
             setMovementMethod(ArrowKeyMovementMethod.getInstance());
-        } else if (editable) {
-            createEditorIfNeeded();
-            mEditor.mKeyListener = TextKeyListener.getInstance();
-            mEditor.mInputType = EditorInfo.TYPE_CLASS_TEXT;
         } else {
             if (mEditor != null) mEditor.mKeyListener = null;
 
@@ -8536,13 +8536,12 @@
                 handled |= mClickableSpanOnClickGestureDetector.onTouchEvent(event);
             }
 
-            final boolean textIsSelectable = isTextSelectable();
-            if (touchIsFinished && (isTextEditable() || textIsSelectable)) {
+            if (touchIsFinished && (isTextEditable() || isTextSelectable())) {
                 // Show the IME, except when selecting in read-only text.
                 final InputMethodManager imm = InputMethodManager.peekInstance();
                 viewClicked(imm);
-                if (!textIsSelectable && mEditor.mShowSoftInputOnFocus) {
-                    handled |= imm != null && imm.showSoftInput(this, 0);
+                if (isTextEditable() && mEditor.mShowSoftInputOnFocus && imm != null) {
+                    imm.showSoftInput(this, 0);
                 }
 
                 // The above condition ensures that the mEditor is not null
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index b7e5718..e46dfc4 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -39,6 +39,7 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
+import java.util.List;
 import java.util.StringTokenizer;
 
 public class ProcessCpuTracker {
@@ -177,6 +178,11 @@
 
     private byte[] mBuffer = new byte[4096];
 
+    public interface FilterStats {
+        /** Which stats to pick when filtering */
+        boolean needed(Stats stats);
+    }
+
     public static class Stats {
         public final int pid;
         public final int uid;
@@ -695,6 +701,18 @@
         return mProcStats.get(index);
     }
 
+    final public List<Stats> getStats(FilterStats filter) {
+        final ArrayList<Stats> statses = new ArrayList<>(mProcStats.size());
+        final int N = mProcStats.size();
+        for (int p = 0; p < N; p++) {
+            Stats stats = mProcStats.get(p);
+            if (filter.needed(stats)) {
+                statses.add(stats);
+            }
+        }
+        return statses;
+    }
+
     final public int countWorkingStats() {
         buildWorkingProcs();
         return mWorkingProcs.size();
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index 02e8af0..50dd33a 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -28,8 +28,9 @@
      * FLAG_SHOW_ON_LOCK_SCREEN.
      *
      * @param isOccluded Whether the Keyguard is occluded by another window.
+     * @param animate Whether to play an animation for the state change.
      */
-    void setOccluded(boolean isOccluded);
+    void setOccluded(boolean isOccluded, boolean animate);
 
     void addStateMonitorCallback(IKeyguardStateCallback callback);
     void verifyUnlock(IKeyguardExitCallback callback);
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index fbc51cd..5a50fbf 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -79,6 +79,9 @@
     private static final String LOG_FILES_FILE = "log-files.xml";
     private static final AtomicFile sFile = new AtomicFile(new File(
             Environment.getDataSystemDirectory(), LOG_FILES_FILE));
+    private static final String LAST_HEADER_FILE = "last-header.txt";
+    private static final File lastHeaderFile = new File(
+            Environment.getDataSystemDirectory(), LAST_HEADER_FILE);
 
     @Override
     public void onReceive(final Context context, Intent intent) {
@@ -113,9 +116,17 @@
         Downloads.removeAllDownloadsByPackage(context, OLD_UPDATER_PACKAGE, OLD_UPDATER_CLASS);
     }
 
-    private void logBootEvents(Context ctx) throws IOException {
-        final DropBoxManager db = (DropBoxManager) ctx.getSystemService(Context.DROPBOX_SERVICE);
-        final String headers = new StringBuilder(512)
+    private String getPreviousBootHeaders() {
+        try {
+            return FileUtils.readTextFile(lastHeaderFile, 0, null);
+        } catch (IOException e) {
+            Slog.e(TAG, "Error reading " + lastHeaderFile, e);
+            return null;
+        }
+    }
+
+    private String getCurrentBootHeaders() throws IOException {
+        return new StringBuilder(512)
             .append("Build: ").append(Build.FINGERPRINT).append("\n")
             .append("Hardware: ").append(Build.BOARD).append("\n")
             .append("Revision: ")
@@ -125,6 +136,31 @@
             .append("Kernel: ")
             .append(FileUtils.readTextFile(new File("/proc/version"), 1024, "...\n"))
             .append("\n").toString();
+    }
+
+
+    private String getBootHeadersToLogAndUpdate() throws IOException {
+        final String oldHeaders = getPreviousBootHeaders();
+        final String newHeaders = getCurrentBootHeaders();
+
+        try {
+            FileUtils.stringToFile(lastHeaderFile, newHeaders);
+        } catch (IOException e) {
+            Slog.e(TAG, "Error writing " + lastHeaderFile, e);
+        }
+
+        if (oldHeaders == null) {
+            // If we failed to read the old headers, use the current headers
+            // but note this in the headers so we know
+            return "isPrevious: false\n" + newHeaders;
+        }
+
+        return "isPrevious: true\n" + oldHeaders;
+    }
+
+    private void logBootEvents(Context ctx) throws IOException {
+        final DropBoxManager db = (DropBoxManager) ctx.getSystemService(Context.DROPBOX_SERVICE);
+        final String headers = getBootHeadersToLogAndUpdate();
         final String bootReason = SystemProperties.get("ro.boot.bootreason", null);
 
         String recovery = RecoverySystem.handleAftermath(ctx);
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index a5e94a10..0f04f6d 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -126,7 +126,7 @@
  */
 class JavaPixelAllocator : public SkBRDAllocator {
 public:
-    JavaPixelAllocator(JNIEnv* env);
+    explicit JavaPixelAllocator(JNIEnv* env);
     ~JavaPixelAllocator();
 
     virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) override;
@@ -214,7 +214,7 @@
 
 class AshmemPixelAllocator : public SkBitmap::Allocator {
 public:
-    AshmemPixelAllocator(JNIEnv* env);
+    explicit AshmemPixelAllocator(JNIEnv* env);
     ~AshmemPixelAllocator();
     virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
     android::Bitmap* getStorageObjAndReset() {
diff --git a/core/jni/android/graphics/Utils.h b/core/jni/android/graphics/Utils.h
index d1a74a0..fffec5b 100644
--- a/core/jni/android/graphics/Utils.h
+++ b/core/jni/android/graphics/Utils.h
@@ -28,7 +28,7 @@
 
 class AssetStreamAdaptor : public SkStreamRewindable {
 public:
-    AssetStreamAdaptor(Asset*);
+    explicit AssetStreamAdaptor(Asset*);
 
     virtual bool rewind();
     virtual size_t read(void* buffer, size_t size);
@@ -53,7 +53,7 @@
  */
 class AutoFDSeek {
 public:
-    AutoFDSeek(int fd) : fFD(fd) {
+    explicit AutoFDSeek(int fd) : fFD(fd) {
         fCurr = ::lseek(fd, 0, SEEK_CUR);
     }
     ~AutoFDSeek() {
diff --git a/core/jni/android/graphics/YuvToJpegEncoder.h b/core/jni/android/graphics/YuvToJpegEncoder.h
index 1ea844a..7e7b935 100644
--- a/core/jni/android/graphics/YuvToJpegEncoder.h
+++ b/core/jni/android/graphics/YuvToJpegEncoder.h
@@ -18,7 +18,7 @@
      */
     static YuvToJpegEncoder* create(int pixelFormat, int* strides);
 
-    YuvToJpegEncoder(int* strides);
+    explicit YuvToJpegEncoder(int* strides);
 
     /** Encode YUV data to jpeg,  which is output to a stream.
      *
@@ -47,7 +47,7 @@
 
 class Yuv420SpToJpegEncoder : public YuvToJpegEncoder {
 public:
-    Yuv420SpToJpegEncoder(int* strides);
+    explicit Yuv420SpToJpegEncoder(int* strides);
     virtual ~Yuv420SpToJpegEncoder() {}
 
 private:
@@ -61,7 +61,7 @@
 
 class Yuv422IToJpegEncoder : public YuvToJpegEncoder {
 public:
-    Yuv422IToJpegEncoder(int* strides);
+    explicit Yuv422IToJpegEncoder(int* strides);
     virtual ~Yuv422IToJpegEncoder() {}
 
 private:
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index 7213414..3fc3aaf 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -16,6 +16,7 @@
 
 #undef LOG_TAG
 #define LOG_TAG "CursorWindow"
+#define LOG_NDEBUG 0
 
 #include <inttypes.h>
 #include <jni.h>
@@ -30,6 +31,11 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#undef LOG_NDEBUG
+#define LOG_NDEBUG 1
 
 #include <androidfw/CursorWindow.h>
 #include "android_os_Parcel.h"
@@ -61,6 +67,22 @@
     jniThrowException(env, "java/lang/IllegalStateException", msg.string());
 }
 
+static int getFdCount() {
+    char fdpath[PATH_MAX];
+    int count = 0;
+    snprintf(fdpath, PATH_MAX, "/proc/%d/fd", getpid());
+    DIR *dir = opendir(fdpath);
+    if (dir != NULL) {
+        struct dirent *dirent;
+        while ((dirent = readdir(dir))) {
+            count++;
+        }
+        count -= 2; // discount "." and ".."
+        closedir(dir);
+    }
+    return count;
+}
+
 static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring nameObj, jint cursorWindowSize) {
     String8 name;
     const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
@@ -85,7 +107,8 @@
     CursorWindow* window;
     status_t status = CursorWindow::createFromParcel(parcel, &window);
     if (status || !window) {
-        ALOGE("Could not create CursorWindow from Parcel due to error %d.", status);
+        ALOGE("Could not create CursorWindow from Parcel due to error %d, process fd count=%d",
+                status, getFdCount());
         return 0;
     }
 
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index f899c00..7ec17bf 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -235,7 +235,7 @@
 {
     struct usb_device* device = get_device_from_object(env, thiz);
     if (!device) {
-        ALOGE("device is closed in native_request_wait");
+        ALOGE("device is closed in native_get_serial");
         return NULL;
     }
     char* serial = usb_device_get_serial(device);
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index 8bee9c9..3644410 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -26,6 +26,10 @@
 #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>
 
@@ -51,6 +55,10 @@
 static constexpr size_t HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
 static constexpr size_t MSG_HEADER_SIZE_LOAD_APP = MSG_HEADER_SIZE + 2;
 
+// Monotonically increasing clock we use to determine if we can cancel
+// a transaction.
+using std::chrono::steady_clock;
+
 namespace android {
 
 namespace {
@@ -107,6 +115,17 @@
     struct hub_app_info appInfo; // returned from the HAL
 };
 
+
+// If a transaction takes longer than this, we'll allow it to be
+// canceled by a new transaction.  Note we do _not_ automatically
+// cancel a transaction after this much time.  We can have a
+// legal transaction which takes longer than this amount of time,
+// as long as no other new transactions are attempted after this
+// time has expired.
+// TODO(b/31105001): Establish a clean timing approach for all
+// of our HAL interactions.
+constexpr auto kMinTransactionCancelTime = std::chrono::seconds(29);
+
 /*
  * TODO(ashutoshj): From original code review:
  *
@@ -148,6 +167,7 @@
     std::mutex m;                 // mutex for manager
     hub_messages_e txnIdentifier; // What are we doing
     void *txnData;                // Details
+    steady_clock::time_point firstTimeTxnCanBeCanceled;
 };
 
 struct contextHubServiceDb_s {
@@ -177,25 +197,40 @@
     std::lock_guard<std::mutex>lock(mgr->m);
 
     mgr->txnPending = true;
+    mgr->firstTimeTxnCanBeCanceled = steady_clock::now() +
+        kMinTransactionCancelTime;
     mgr->txnData = txnData;
     mgr->txnIdentifier = txnIdentifier;
 
     return 0;
 }
 
-static int closeTxn() {
+// Only call this if you hold the db.txnManager.m lock.
+static void closeTxnUnlocked() {
     txnManager_s *mgr = &db.txnManager;
-    std::lock_guard<std::mutex>lock(mgr->m);
     mgr->txnPending = false;
     free(mgr->txnData);
     mgr->txnData = nullptr;
+}
 
+static int closeTxn() {
+    std::lock_guard<std::mutex>lock(db.txnManager.m);
+    closeTxnUnlocked();
     return 0;
 }
 
+// If a transaction has been pending for longer than
+// kMinTransactionCancelTime, this call will "cancel" that
+// transaction and return that there are none pending.
 static bool isTxnPending() {
     txnManager_s *mgr = &db.txnManager;
     std::lock_guard<std::mutex>lock(mgr->m);
+    if (mgr->txnPending) {
+        if (steady_clock::now() >= mgr->firstTimeTxnCanBeCanceled) {
+            ALOGW("Transaction canceled");
+            closeTxnUnlocked();
+        }
+    }
     return mgr->txnPending;
 }
 
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 132ed95..97833a0 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -26,8 +26,8 @@
 #include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <hidl/IServiceManager.h>
+#include <hidl/Status.h>
 #include <hwbinder/ProcessState.h>
-#include <hwbinder/Status.h>
 #include <nativehelper/ScopedLocalRef.h>
 
 #include "core_jni_helpers.h"
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index 6972cf1..b2dee06 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -24,7 +24,7 @@
 
 #include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
-#include <hwbinder/Status.h>
+#include <hidl/Status.h>
 #include <nativehelper/ScopedLocalRef.h>
 
 #include "core_jni_helpers.h"
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 226d61b..d453b29 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -26,7 +26,7 @@
 
 #include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
-#include <hwbinder/Status.h>
+#include <hidl/Status.h>
 #include <nativehelper/ScopedLocalRef.h>
 
 #include "core_jni_helpers.h"
diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp
index 81ba368..3023ba8 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -25,7 +25,7 @@
 #include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <hidl/IServiceManager.h>
-#include <hwbinder/Status.h>
+#include <hidl/Status.h>
 #include <nativehelper/ScopedLocalRef.h>
 
 #include "core_jni_helpers.h"
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 0d8a95c..73b3f52 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -371,7 +371,12 @@
     if (sur != NULL) {
         bufferProducer = sur->getIGraphicBufferProducer();
     }
-    SurfaceComposerClient::setDisplaySurface(token, bufferProducer);
+    status_t err = SurfaceComposerClient::setDisplaySurface(token,
+            bufferProducer);
+    if (err != NO_ERROR) {
+        doThrowIAE(env, "Illegal Surface, could not enable async mode. Was this"
+                " Surface created with singleBufferMode?");
+    }
 }
 
 static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz,
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index cdfb722..e48065c 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -55,6 +55,7 @@
 #include "ScopedLocalRef.h"
 #include "ScopedPrimitiveArray.h"
 #include "ScopedUtfChars.h"
+#include "fd_utils-inl.h"
 
 #include "nativebridge/native_bridge.h"
 
@@ -455,6 +456,9 @@
 }
 #endif
 
+// The list of open zygote file descriptors.
+static FileDescriptorTable* gOpenFdTable = NULL;
+
 // Utility routine to fork zygote and specialize the child process.
 static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                      jint debug_flags, jobjectArray javaRlimits,
@@ -469,6 +473,22 @@
   SetForkLoad(true);
 #endif
 
+  // Close any logging related FDs before we start evaluating the list of
+  // file descriptors.
+  __android_log_close();
+
+  // If this is the first fork for this zygote, create the open FD table.
+  // If it isn't, we just need to check whether the list of open files has
+  // changed (and it shouldn't in the normal case).
+  if (gOpenFdTable == NULL) {
+    gOpenFdTable = FileDescriptorTable::Create();
+    if (gOpenFdTable == NULL) {
+      RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table.");
+    }
+  } else if (!gOpenFdTable->Restat()) {
+    RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
+  }
+
   ResetNicePriority(env);
 
   pid_t pid = fork();
@@ -480,6 +500,12 @@
     // Clean up any descriptors which must be closed immediately
     DetachDescriptors(env, fdsToClose);
 
+    // Re-open all remaining open file descriptors so that they aren't shared
+    // with the zygote across a fork.
+    if (!gOpenFdTable->ReopenOrDetach()) {
+      RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors.");
+    }
+
     // Keep capabilities across UID change, unless we're staying root.
     if (uid != 0) {
       EnableKeepCapabilities(env);
diff --git a/core/jni/fd_utils-inl.h b/core/jni/fd_utils-inl.h
new file mode 100644
index 0000000..2b36c9f
--- /dev/null
+++ b/core/jni/fd_utils-inl.h
@@ -0,0 +1,533 @@
+/*
+ * 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.
+ */
+
+#include <string>
+#include <unordered_map>
+#include <set>
+#include <vector>
+#include <algorithm>
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <cutils/log.h>
+#include "JNIHelp.h"
+#include "ScopedPrimitiveArray.h"
+
+// Whitelist of open paths that the zygote is allowed to keep open.
+//
+// In addition to the paths listed here, all files ending with
+// ".jar" under /system/framework" are whitelisted. See
+// FileDescriptorInfo::IsWhitelisted for the canonical definition.
+//
+// If the whitelisted path is associated with a regular file or a
+// character device, the file is reopened after a fork with the same
+// offset and mode. If the whilelisted  path is associated with a
+// AF_UNIX socket, the socket will refer to /dev/null after each
+// fork, and all operations on it will fail.
+static const char* kPathWhitelist[] = {
+  "/dev/null",
+  "/dev/pmsg0",
+  "/dev/socket/zygote",
+  "/dev/socket/zygote_secondary",
+  "/system/etc/event-log-tags",
+  "/sys/kernel/debug/tracing/trace_marker",
+  "/system/framework/framework-res.apk",
+  "/dev/urandom",
+  "/dev/ion",
+  "/dev/dri/renderD129", // Fixes b/31172436
+};
+
+static const char* kFdPath = "/proc/self/fd";
+
+// Keeps track of all relevant information (flags, offset etc.) of an
+// open zygote file descriptor.
+class FileDescriptorInfo {
+ public:
+  // Create a FileDescriptorInfo for a given file descriptor. Returns
+  // |NULL| if an error occurred.
+  static FileDescriptorInfo* createFromFd(int fd) {
+    struct stat f_stat;
+    // This should never happen; the zygote should always have the right set
+    // of permissions required to stat all its open files.
+    if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
+      ALOGE("Unable to stat fd %d : %s", fd, strerror(errno));
+      return NULL;
+    }
+
+    if (S_ISSOCK(f_stat.st_mode)) {
+      std::string socket_name;
+      if (!GetSocketName(fd, &socket_name)) {
+        return NULL;
+      }
+
+      if (!IsWhitelisted(socket_name)) {
+        ALOGE("Socket name not whitelisted : %s (fd=%d)", socket_name.c_str(), fd);
+        return NULL;
+      }
+
+      return new FileDescriptorInfo(fd);
+    }
+
+    // We only handle whitelisted regular files and character devices. Whitelisted
+    // character devices must provide a guarantee of sensible behaviour when
+    // reopened.
+    //
+    // S_ISDIR : Not supported. (We could if we wanted to, but it's unused).
+    // S_ISLINK : Not supported.
+    // S_ISBLK : Not supported.
+    // S_ISFIFO : Not supported. Note that the zygote uses pipes to communicate
+    // with the child process across forks but those should have been closed
+    // before we got to this point.
+    if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
+      ALOGE("Unsupported st_mode %d", f_stat.st_mode);
+      return NULL;
+    }
+
+    std::string file_path;
+    if (!Readlink(fd, &file_path)) {
+      return NULL;
+    }
+
+    if (!IsWhitelisted(file_path)) {
+      ALOGE("Not whitelisted : %s", file_path.c_str());
+      return NULL;
+    }
+
+    // File descriptor flags : currently on FD_CLOEXEC. We can set these
+    // using F_SETFD - we're single threaded at this point of execution so
+    // there won't be any races.
+    const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
+    if (fd_flags == -1) {
+      ALOGE("Failed fcntl(%d, F_GETFD) : %s", fd, strerror(errno));
+      return NULL;
+    }
+
+    // File status flags :
+    // - File access mode : (O_RDONLY, O_WRONLY...) we'll pass these through
+    //   to the open() call.
+    //
+    // - File creation flags : (O_CREAT, O_EXCL...) - there's not much we can
+    //   do about these, since the file has already been created. We shall ignore
+    //   them here.
+    //
+    // - Other flags : We'll have to set these via F_SETFL. On linux, F_SETFL
+    //   can only set O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
+    //   In particular, it can't set O_SYNC and O_DSYNC. We'll have to test for
+    //   their presence and pass them in to open().
+    int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
+    if (fs_flags == -1) {
+      ALOGE("Failed fcntl(%d, F_GETFL) : %s", fd, strerror(errno));
+      return NULL;
+    }
+
+    // File offset : Ignore the offset for non seekable files.
+    const off_t offset = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR));
+
+    // We pass the flags that open accepts to open, and use F_SETFL for
+    // the rest of them.
+    static const int kOpenFlags = (O_RDONLY | O_WRONLY | O_RDWR | O_DSYNC | O_SYNC);
+    int open_flags = fs_flags & (kOpenFlags);
+    fs_flags = fs_flags & (~(kOpenFlags));
+
+    return new FileDescriptorInfo(f_stat, file_path, fd, open_flags, fd_flags, fs_flags, offset);
+  }
+
+  // Checks whether the file descriptor associated with this object
+  // refers to the same description.
+  bool Restat() const {
+    struct stat f_stat;
+    if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
+      return false;
+    }
+
+    return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
+  }
+
+  bool ReopenOrDetach() const {
+    if (is_sock) {
+      return DetachSocket();
+    }
+
+    // NOTE: This might happen if the file was unlinked after being opened.
+    // It's a common pattern in the case of temporary files and the like but
+    // we should not allow such usage from the zygote.
+    const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
+
+    if (new_fd == -1) {
+      ALOGE("Failed open(%s, %d) : %s", file_path.c_str(), open_flags, strerror(errno));
+      return false;
+    }
+
+    if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
+      close(new_fd);
+      ALOGE("Failed fcntl(%d, F_SETFD, %x) : %s", new_fd, fd_flags, strerror(errno));
+      return false;
+    }
+
+    if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
+      close(new_fd);
+      ALOGE("Failed fcntl(%d, F_SETFL, %x) : %s", new_fd, fs_flags, strerror(errno));
+      return false;
+    }
+
+    if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
+      close(new_fd);
+      ALOGE("Failed lseek64(%d, SEEK_SET) : %s", new_fd, strerror(errno));
+      return false;
+    }
+
+    if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
+      close(new_fd);
+      ALOGE("Failed dup2(%d, %d) : %s", fd, new_fd, strerror(errno));
+      return false;
+    }
+
+    close(new_fd);
+
+    return true;
+  }
+
+  const int fd;
+  const struct stat stat;
+  const std::string file_path;
+  const int open_flags;
+  const int fd_flags;
+  const int fs_flags;
+  const off_t offset;
+  const bool is_sock;
+
+ private:
+  FileDescriptorInfo(int fd) :
+    fd(fd),
+    stat(),
+    open_flags(0),
+    fd_flags(0),
+    fs_flags(0),
+    offset(0),
+    is_sock(true) {
+  }
+
+  FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
+                     int fd_flags, int fs_flags, off_t offset) :
+    fd(fd),
+    stat(stat),
+    file_path(file_path),
+    open_flags(open_flags),
+    fd_flags(fd_flags),
+    fs_flags(fs_flags),
+    offset(offset),
+    is_sock(false) {
+  }
+
+  // Returns true iff. a given path is whitelisted. A path is whitelisted
+  // if it belongs to the whitelist (see kPathWhitelist) or if it's a path
+  // under /system/framework that ends with ".jar".
+  static bool IsWhitelisted(const std::string& path) {
+    for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) {
+      if (kPathWhitelist[i] == path) {
+        return true;
+      }
+    }
+
+    static const std::string kFrameworksPrefix = "/system/framework/";
+    static const std::string kJarSuffix = ".jar";
+    if (path.compare(0, kFrameworksPrefix.size(), kFrameworksPrefix) == 0 &&
+        path.compare(path.size() - kJarSuffix.size(), kJarSuffix.size(), kJarSuffix) == 0) {
+      return true;
+    }
+    return false;
+  }
+
+  // TODO: Call android::base::Readlink instead of copying the code here.
+  static bool Readlink(const int fd, std::string* result) {
+    char path[64];
+    snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
+
+    // Code copied from android::base::Readlink starts here :
+
+    // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer,
+    // and truncates to whatever size you do supply, so it can't be used to query.
+    // We could call lstat first, but that would introduce a race condition that
+    // we couldn't detect.
+    // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here.
+    char buf[4096];
+    ssize_t len = readlink(path, buf, sizeof(buf));
+    if (len == -1) return false;
+
+    result->assign(buf, len);
+    return true;
+  }
+
+  // Returns the locally-bound name of the socket |fd|. Returns true
+  // iff. all of the following hold :
+  //
+  // - the socket's sa_family is AF_UNIX.
+  // - the length of the path is greater than zero (i.e, not an unnamed socket).
+  // - the first byte of the path isn't zero (i.e, not a socket with an abstract
+  //   address).
+  static bool GetSocketName(const int fd, std::string* result) {
+    sockaddr_storage ss;
+    sockaddr* addr = reinterpret_cast<sockaddr*>(&ss);
+    socklen_t addr_len = sizeof(ss);
+
+    if (TEMP_FAILURE_RETRY(getsockname(fd, addr, &addr_len)) == -1) {
+      ALOGE("Failed getsockname(%d) : %s", fd, strerror(errno));
+      return false;
+    }
+
+    if (addr->sa_family != AF_UNIX) {
+      ALOGE("Unsupported socket (fd=%d) with family %d", fd, addr->sa_family);
+      return false;
+    }
+
+    const sockaddr_un* unix_addr = reinterpret_cast<const sockaddr_un*>(&ss);
+
+    size_t path_len = addr_len - offsetof(struct sockaddr_un, sun_path);
+    // This is an unnamed local socket, we do not accept it.
+    if (path_len == 0) {
+      ALOGE("Unsupported AF_UNIX socket (fd=%d) with empty path.", fd);
+      return false;
+    }
+
+    // This is a local socket with an abstract address, we do not accept it.
+    if (unix_addr->sun_path[0] == '\0') {
+      ALOGE("Unsupported AF_UNIX socket (fd=%d) with abstract address.", fd);
+      return false;
+    }
+
+    // If we're here, sun_path must refer to a null terminated filesystem
+    // pathname (man 7 unix). Remove the terminator before assigning it to an
+    // std::string.
+    if (unix_addr->sun_path[path_len - 1] ==  '\0') {
+      --path_len;
+    }
+
+    result->assign(unix_addr->sun_path, path_len);
+    return true;
+  }
+
+  bool DetachSocket() const {
+    const int dev_null_fd = open("/dev/null", O_RDWR);
+    if (dev_null_fd < 0) {
+      ALOGE("Failed to open /dev/null : %s", strerror(errno));
+      return false;
+    }
+
+    if (dup2(dev_null_fd, fd) == -1) {
+      ALOGE("Failed dup2 on socket descriptor %d : %s", fd, strerror(errno));
+      return false;
+    }
+
+    if (close(dev_null_fd) == -1) {
+      ALOGE("Failed close(%d) : %s", dev_null_fd, strerror(errno));
+      return false;
+    }
+
+    return true;
+  }
+
+  DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
+};
+
+// A FileDescriptorTable is a collection of FileDescriptorInfo objects
+// keyed by their FDs.
+class FileDescriptorTable {
+ public:
+  // Creates a new FileDescriptorTable. This function scans
+  // /proc/self/fd for the list of open file descriptors and collects
+  // information about them. Returns NULL if an error occurs.
+  static FileDescriptorTable* Create() {
+    DIR* d = opendir(kFdPath);
+    if (d == NULL) {
+      ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
+      return NULL;
+    }
+    int dir_fd = dirfd(d);
+    dirent* e;
+
+    std::unordered_map<int, FileDescriptorInfo*> open_fd_map;
+    while ((e = readdir(d)) != NULL) {
+      const int fd = ParseFd(e, dir_fd);
+      if (fd == -1) {
+        continue;
+      }
+
+      FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd);
+      if (info == NULL) {
+        if (closedir(d) == -1) {
+          ALOGE("Unable to close directory : %s", strerror(errno));
+        }
+        return NULL;
+      }
+      open_fd_map[fd] = info;
+    }
+
+    if (closedir(d) == -1) {
+      ALOGE("Unable to close directory : %s", strerror(errno));
+      return NULL;
+    }
+    return new FileDescriptorTable(open_fd_map);
+  }
+
+  bool Restat() {
+    std::set<int> open_fds;
+
+    // First get the list of open descriptors.
+    DIR* d = opendir(kFdPath);
+    if (d == NULL) {
+      ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
+      return false;
+    }
+
+    int dir_fd = dirfd(d);
+    dirent* e;
+    while ((e = readdir(d)) != NULL) {
+      const int fd = ParseFd(e, dir_fd);
+      if (fd == -1) {
+        continue;
+      }
+
+      open_fds.insert(fd);
+    }
+
+    if (closedir(d) == -1) {
+      ALOGE("Unable to close directory : %s", strerror(errno));
+      return false;
+    }
+
+    return RestatInternal(open_fds);
+  }
+
+  // Reopens all file descriptors that are contained in the table. Returns true
+  // if all descriptors were successfully re-opened or detached, and false if an
+  // error occurred.
+  bool ReopenOrDetach() {
+    std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
+    for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
+      const FileDescriptorInfo* info = it->second;
+      if (info == NULL || !info->ReopenOrDetach()) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+ private:
+  FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map)
+      : open_fd_map_(map) {
+  }
+
+  bool RestatInternal(std::set<int>& open_fds) {
+    bool error = false;
+
+    // Iterate through the list of file descriptors we've already recorded
+    // and check whether :
+    //
+    // (a) they continue to be open.
+    // (b) they refer to the same file.
+    std::unordered_map<int, FileDescriptorInfo*>::iterator it;
+    for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
+      std::set<int>::const_iterator element = open_fds.find(it->first);
+      if (element == open_fds.end()) {
+        // The entry from the file descriptor table is no longer in the list
+        // of open files. We warn about this condition and remove it from
+        // the list of FDs under consideration.
+        //
+        // TODO(narayan): This will be an error in a future android release.
+        // error = true;
+        // ALOGW("Zygote closed file descriptor %d.", it->first);
+        open_fd_map_.erase(it);
+      } else {
+        // The entry from the file descriptor table is still open. Restat
+        // it and check whether it refers to the same file.
+        open_fds.erase(element);
+        const bool same_file = it->second->Restat();
+        if (!same_file) {
+          // The file descriptor refers to a different description. We must
+          // update our entry in the table.
+          delete it->second;
+          it->second = FileDescriptorInfo::createFromFd(*element);
+          if (it->second == NULL) {
+            // The descriptor no longer no longer refers to a whitelisted file.
+            // We flag an error and remove it from the list of files we're
+            // tracking.
+            error = true;
+            open_fd_map_.erase(it);
+          }
+        } else {
+          // It's the same file. Nothing to do here.
+        }
+      }
+    }
+
+    if (open_fds.size() > 0) {
+      // The zygote has opened new file descriptors since our last inspection.
+      // We warn about this condition and add them to our table.
+      //
+      // TODO(narayan): This will be an error in a future android release.
+      // error = true;
+      // ALOGW("Zygote opened %zd new file descriptor(s).", open_fds.size());
+
+      // TODO(narayan): This code will be removed in a future android release.
+      std::set<int>::const_iterator it;
+      for (it = open_fds.begin(); it != open_fds.end(); ++it) {
+        const int fd = (*it);
+        FileDescriptorInfo* info = FileDescriptorInfo::createFromFd(fd);
+        if (info == NULL) {
+          // A newly opened file is not on the whitelist. Flag an error and
+          // continue.
+          error = true;
+        } else {
+          // Track the newly opened file.
+          open_fd_map_[fd] = info;
+        }
+      }
+    }
+
+    return !error;
+  }
+
+  static int ParseFd(dirent* e, int dir_fd) {
+    char* end;
+    const int fd = strtol(e->d_name, &end, 10);
+    if ((*end) != '\0') {
+      return -1;
+    }
+
+    // Don't bother with the standard input/output/error, they're handled
+    // specially post-fork anyway.
+    if (fd <= STDERR_FILENO || fd == dir_fd) {
+      return -1;
+    }
+
+    return fd;
+  }
+
+  // Invariant: All values in this unordered_map are non-NULL.
+  std::unordered_map<int, FileDescriptorInfo*> open_fd_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(FileDescriptorTable);
+};
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 70ea4df..003402a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1642,7 +1642,7 @@
 
     <!-- @hide Allows an application to create, remove users and get the list of
          users on the device. Applications holding this permission can only create restricted,
-         guest, managed, and ephemeral users. For creating other kind of users,
+         guest, managed, demo, and ephemeral users. For creating other kind of users,
          {@link android.Manifest.permission#MANAGE_USERS} is needed.
          This permission is not available to third party applications. -->
     <permission android:name="android.permission.CREATE_USERS"
diff --git a/core/res/res/anim/watch_switch_thumb_to_off_animation.xml b/core/res/res/anim/watch_switch_thumb_to_off_animation.xml
deleted file mode 100644
index c300894..0000000
--- a/core/res/res/anim/watch_switch_thumb_to_off_animation.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    android:ordering="sequentially">
-    <objectAnimator
-        android:duration="33"
-        android:interpolator="@android:interpolator/linear"
-        android:propertyName="pathData"
-        android:valueFrom="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueTo="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueType="pathType" />
-    <objectAnimator
-        android:duration="49"
-        android:interpolator="@android:interpolator/linear"
-        android:propertyName="pathData"
-        android:valueFrom="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueTo="M -3.0,-7.0 l 6.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l -6.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueType="pathType" />
-    <objectAnimator
-        android:duration="83"
-        android:interpolator="@android:interpolator/linear"
-        android:propertyName="pathData"
-        android:valueFrom="M -3.0,-7.0 l 6.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l -6.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueTo="M -3.0,-7.0 l 6.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l -6.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueType="pathType" />
-    <objectAnimator
-        android:duration="50"
-        android:interpolator="@android:interpolator/linear"
-        android:propertyName="pathData"
-        android:valueFrom="M -3.0,-7.0 l 6.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l -6.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueTo="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueType="pathType" />
-    <objectAnimator
-        android:duration="33"
-        android:interpolator="@android:interpolator/linear"
-        android:propertyName="pathData"
-        android:valueFrom="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueTo="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueType="pathType" />
-</set>
diff --git a/core/res/res/anim/watch_switch_thumb_to_on_animation.xml b/core/res/res/anim/watch_switch_thumb_to_on_animation.xml
deleted file mode 100644
index c300894..0000000
--- a/core/res/res/anim/watch_switch_thumb_to_on_animation.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    android:ordering="sequentially">
-    <objectAnimator
-        android:duration="33"
-        android:interpolator="@android:interpolator/linear"
-        android:propertyName="pathData"
-        android:valueFrom="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueTo="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueType="pathType" />
-    <objectAnimator
-        android:duration="49"
-        android:interpolator="@android:interpolator/linear"
-        android:propertyName="pathData"
-        android:valueFrom="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueTo="M -3.0,-7.0 l 6.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l -6.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueType="pathType" />
-    <objectAnimator
-        android:duration="83"
-        android:interpolator="@android:interpolator/linear"
-        android:propertyName="pathData"
-        android:valueFrom="M -3.0,-7.0 l 6.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l -6.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueTo="M -3.0,-7.0 l 6.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l -6.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueType="pathType" />
-    <objectAnimator
-        android:duration="50"
-        android:interpolator="@android:interpolator/linear"
-        android:propertyName="pathData"
-        android:valueFrom="M -3.0,-7.0 l 6.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l -6.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueTo="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueType="pathType" />
-    <objectAnimator
-        android:duration="33"
-        android:interpolator="@android:interpolator/linear"
-        android:propertyName="pathData"
-        android:valueFrom="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueTo="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z"
-        android:valueType="pathType" />
-</set>
diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..371469c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..e477260
--- /dev/null
+++ b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..19a1bd3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..79dc733
--- /dev/null
+++ b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..6d921c0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/watch_switch_track_mtrl.png b/core/res/res/drawable-hdpi/watch_switch_track_mtrl.png
new file mode 100644
index 0000000..ecee3e1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/watch_switch_track_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..7f7ca14
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..52120b8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..d6e9be9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..8d76393
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..ca9c66e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_track_mtrl.png b/core/res/res/drawable-xhdpi/watch_switch_track_mtrl.png
new file mode 100644
index 0000000..1aa5442
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/watch_switch_track_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..c0d72d7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..d7c0ec0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..5815ba9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..41da8c0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..975eb01
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl.png b/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl.png
new file mode 100644
index 0000000..af2042b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl.png
Binary files differ
diff --git a/core/res/res/drawable/watch_switch_thumb_material.xml b/core/res/res/drawable/watch_switch_thumb_material.xml
deleted file mode 100644
index 3463a4f..0000000
--- a/core/res/res/drawable/watch_switch_thumb_material.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="20dp"
-    android:height="40dp"
-    android:viewportHeight="40"
-    android:viewportWidth="20">
-    <group
-        android:translateX="10"
-        android:translateY="20">
-        <path
-            android:name="thumb_path"
-            android:fillColor="@color/white"
-            android:pathData="M 0.0,-7.0 l 0.0,0.0 c 3.8659932486,0.0 7.0,3.1340067514 7.0,7.0 l 0.0,0.0 c 0.0,3.8659932486 -3.1340067514,7.0 -7.0,7.0 l 0.0,0.0 c -3.8659932486,0.0 -7.0,-3.1340067514 -7.0,-7.0 l 0.0,0.0 c 0.0,-3.8659932486 3.1340067514,-7.0 7.0,-7.0 Z" />
-    </group>
-</vector>
diff --git a/core/res/res/drawable/watch_switch_thumb_material_anim.xml b/core/res/res/drawable/watch_switch_thumb_material_anim.xml
index 686fb97..9e3e893 100644
--- a/core/res/res/drawable/watch_switch_thumb_material_anim.xml
+++ b/core/res/res/drawable/watch_switch_thumb_material_anim.xml
@@ -15,21 +15,79 @@
     android:constantSize="true">
     <item
         android:id="@+id/off"
-        android:drawable="@drawable/watch_switch_thumb_material"
+        android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
         android:state_enabled="false" />
     <item
         android:id="@+id/on"
-        android:drawable="@drawable/watch_switch_thumb_material"
+        android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
         android:state_checked="true" />
     <item
         android:id="@+id/off"
-        android:drawable="@drawable/watch_switch_thumb_material" />
+        android:drawable="@drawable/watch_switch_thumb_mtrl_14w" />
     <transition
-        android:drawable="@drawable/watch_switch_thumb_to_on_anim_mtrl"
         android:fromId="@id/off"
-        android:toId="@id/on" />
+        android:toId="@id/on">
+        <animation-list>
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
+                android:duration="30" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_18w"
+                android:duration="75" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
+                android:duration="30" />
+        </animation-list>
+    </transition>
     <transition
-        android:drawable="@drawable/watch_switch_thumb_to_off_anim_mtrl"
         android:fromId="@id/on"
-        android:toId="@id/off" />
+        android:toId="@id/off">
+        <animation-list>
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
+                android:duration="30" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_18w"
+                android:duration="75" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
+                android:duration="30" />
+        </animation-list>
+    </transition>
 </animated-selector>
diff --git a/core/res/res/drawable/watch_switch_thumb_to_off_anim_mtrl.xml b/core/res/res/drawable/watch_switch_thumb_to_off_anim_mtrl.xml
deleted file mode 100644
index 2c6ba2f..0000000
--- a/core/res/res/drawable/watch_switch_thumb_to_off_anim_mtrl.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?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.
--->
-
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/watch_switch_thumb_material">
-    <target
-        android:name="thumb_path"
-        android:animation="@anim/watch_switch_thumb_to_off_animation" />
-</animated-vector>
diff --git a/core/res/res/drawable/watch_switch_thumb_to_on_anim_mtrl.xml b/core/res/res/drawable/watch_switch_thumb_to_on_anim_mtrl.xml
deleted file mode 100644
index 9f92361..0000000
--- a/core/res/res/drawable/watch_switch_thumb_to_on_anim_mtrl.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?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.
--->
-
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/watch_switch_thumb_material">
-    <target
-        android:name="thumb_path"
-        android:animation="@anim/watch_switch_thumb_to_on_animation" />
-</animated-vector>
diff --git a/core/res/res/drawable/watch_switch_track_material.xml b/core/res/res/drawable/watch_switch_track_material.xml
deleted file mode 100644
index 00cdadb..0000000
--- a/core/res/res/drawable/watch_switch_track_material.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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.
--->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:gravity="center_vertical|center_horizontal">
-        <shape android:shape="oval">
-            <solid android:color="@android:color/white" />
-            <size
-                android:width="40dp"
-                android:height="40dp" />
-        </shape>
-    </item>
-</layer-list>
\ No newline at end of file
diff --git a/core/res/res/layout-watch/preference_widget_switch.xml b/core/res/res/layout-watch/preference_widget_switch.xml
index ffc00b4..a1a845a 100644
--- a/core/res/res/layout-watch/preference_widget_switch.xml
+++ b/core/res/res/layout-watch/preference_widget_switch.xml
@@ -23,7 +23,8 @@
     android:layout_gravity="center"
     android:thumb="@drawable/watch_switch_thumb_material_anim"
     android:thumbTint="@color/watch_switch_thumb_color_material"
-    android:track="@drawable/watch_switch_track_material"
+    android:thumbTintMode="multiply"
+    android:track="@drawable/watch_switch_track_mtrl"
     android:trackTint="@color/watch_switch_track_color_material"
     android:focusable="false"
     android:clickable="false"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index d5343a8..367c16a 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi het geen internettoegang nie"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Tik vir opsies"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Het oorgeskakel na <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Toestel gebruik <xliff:g id="NEW_NETWORK">%1$s</xliff:g> wanneer <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> geen internetverbinding het nie. Heffings kan geld."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Het oorgeskakel van <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"sellulêre data"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"\'n onbekende netwerktipe"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kon nie aan Wi-Fikoppel nie"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" het \'n swak internetverbinding."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Laat verbinding toe?"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 6eaf947..0f51a6f 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi በይነመረብ መዳረሻ የለውም"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ለአማራጮች መታ ያድርጉ"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"ወደ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ተቀይሯል"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ምንም ዓይነት የበይነመረብ ግንኙነት በማይኖረው ጊዜ መሣሪያዎች <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ን ይጠቀማሉ። ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ።"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"ከ<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ወደ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ተቀይሯል"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"የተንቀሳቃሽ ስልክ ውሂብ"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"ብሉቱዝ"</item>
+    <item msgid="5447331121797802871">"ኤተርኔት"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"አንድ ያልታወቀ አውታረ መረብ ዓይነት"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ወደ Wi-Fi ለማያያዝ አልተቻለም"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ደካማ የበይነመረብ ግንኙነት ኣለው።"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"ግንኙነት ይፈቀድ?"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 234ea8b..a09317f 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1176,6 +1176,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"‏شبكة Wi-Fi غير متصلة بالإنترنت"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"انقر للحصول على الخيارات."</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"تم التبديل إلى <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"يستخدم الجهاز <xliff:g id="NEW_NETWORK">%1$s</xliff:g> عندما لا يتوفر اتصال بالإنترنت في شبكة <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>، ويمكن أن يتم فرض رسوم مقابل ذلك."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"تم التبديل من <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> إلى <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"بيانات شبكة الجوّال"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"بلوتوث"</item>
+    <item msgid="5447331121797802871">"إيثرنت"</item>
+    <item msgid="8257233890381651999">"‏شبكة ظاهرية خاصة (VPN)"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"نوع شبكة غير معروف"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"‏تعذر الاتصال بـ Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" لديها اتصال إنترنت رديء."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"هل تريد السماح بالاتصال؟"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index cf9dfe8..39fdda2 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi-ın İnternetə girişi yoxdur"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Seçimlər üçün tıklayın"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> şəbəkə növünə keçirildi"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> şəbəkəsinin İnternetə çıxışı olmadıqda, cihaz <xliff:g id="NEW_NETWORK">%1$s</xliff:g> şəbəkəsini istifadə edir. Ödəniş tətbiq oluna bilər."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> şəbəkəsindən <xliff:g id="NEW_NETWORK">%2$s</xliff:g> şəbəkəsinə keçirildi"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobil data"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"naməlum şəbəkə növü"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi\'a qoşulmaq alınmadı"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" internet bağlantısı keyfiyyətsizdir."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Bağlantıya icazə verilsin?"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 05e5fff..15e2516 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1101,6 +1101,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi nema pristup internetu"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Dodirnite za opcije"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Prešli ste na tip mreže <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Uređaj koristi tip mreže <xliff:g id="NEW_NETWORK">%1$s</xliff:g> kada tip mreže <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu. Možda će se naplaćivati troškovi."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Prešli ste sa tipa mreže <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na tip mreže <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobilni podaci"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Eternet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"nepoznat tip mreže"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nije moguće povezati sa Wi-Fi mrežom"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima lošu internet vezu."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Želite li da dozvolite povezivanje?"</string>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index e0993b7..5db997c 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -1126,6 +1126,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"У Wi-Fi няма доступу да Інтэрнэту"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Дакраніцеся, каб убачыць параметры"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Выкананы пераход да <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Прылада выкарыстоўвае <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, калі ў <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> няма доступу да інтэрнэту. Можа спаганяцца дадатковая плата."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Выкананы пераход з <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> да <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"сотавая перадача даных"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"невядомы тып сеткі"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Немагчыма падключыцца да Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" дрэннае падключэнне да Інтэрнэту."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Дазволіць падключэнне?"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 8643c13..3680e7f 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi мрежата няма достъп до интернет"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Докоснете за опции"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Превключи се към <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Устройството използва <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, когато <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> няма достъп до интернет. Възможно е да бъдете таксувани."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Превключи се от <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> към <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"мобилни данни"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"виртуална частна мрежа (VPN)"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"неизвестен тип мрежа"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не можа да се свърже с Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" има лоша връзка с интернет."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Да се разреши ли връзката?"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 90afe1c..5b89283 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -215,7 +215,7 @@
     <string name="global_action_lock" msgid="2844945191792119712">"স্ক্রীণ লক"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"পাওয়ার বন্ধ করুন"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"ত্রুটির প্রতিবেদন"</string>
-    <string name="bugreport_title" msgid="2667494803742548533">"ত্রুটির প্রতিবেদন করুন"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"ত্রুটির অভিযোগ করুন"</string>
     <string name="bugreport_message" msgid="398447048750350456">"এটি একটি ই-মেল বার্তা পাঠানোর জন্য আপনার ডিভাইসের বর্তমান অবস্থা সম্পর্কে তথ্য সংগ্রহ করবে৷ ত্রুটির প্রতিবেদন শুরুর সময় থেকে এটি পাঠানোর জন্য প্রস্তুত হতে কিছুটা সময় নেবে; দয়া করে ধৈর্য রাখুন৷"</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ইন্টারেক্টিভ প্রতিবেদন"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"বেশিরভাগ পরিস্থিতিতে এটিকে ব্যবহার করুন৷ এটি আপনাকে প্রতিবেদনের কাজ কতটা হয়েছে তার উপর নজর রাখতে দেয়, সমস্যাটির সম্পর্কে আরো অনেক কিছু লিখতে দেয় এবং স্ক্রীনশটগুলি নিতে দেয়৷ এটি হয়ত প্রতিবেদন করতে খুব বেশি সময় নেয় এমনকি কম-ব্যবহৃত বিভাগগুলি সরিয়ে দিতে পারে৷"</string>
@@ -1007,7 +1007,7 @@
     <string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> সাড়া দিচ্ছে না"</string>
     <string name="anr_process" msgid="6156880875555921105">"<xliff:g id="PROCESS">%1$s</xliff:g> প্রক্রিয়া সাড়া দিচ্ছে না"</string>
     <string name="force_close" msgid="8346072094521265605">"ঠিক আছে"</string>
-    <string name="report" msgid="4060218260984795706">"প্রতিবেদন করুন"</string>
+    <string name="report" msgid="4060218260984795706">"অভিযোগ করুন"</string>
     <string name="wait" msgid="7147118217226317732">"অপেক্ষা করুন"</string>
     <string name="webpage_unresponsive" msgid="3272758351138122503">"পৃষ্ঠাটি কোনো পতিক্রিয়া করছে না৷\n\nআপনি কি এটিকে বন্ধ করতে চান?"</string>
     <string name="launch_warning_title" msgid="1547997780506713581">"অ্যাপ্লিকেশানকে পুনঃনির্দেশিত করা হয়েছে"</string>
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"ওয়াই-ফাই -তে কোনো ইন্টারনেট অ্যাক্সেস নেই"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"বিকল্পগুলির জন্য আলতো চাপুন"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> এ পাল্টানো হয়েছে"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"যখন <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> এর কোনো ইন্টারনেট অ্যাক্সেস থাকে না তখন ডিভাইস <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ব্যবহার করে৷ চার্জ লাগতে পারে৷"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> থেকে <xliff:g id="NEW_NETWORK">%2$s</xliff:g> এ পাল্টানো হয়েছে"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"সেলুলার ডেটা"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"ইথারনেট"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"এই নেটওয়ার্কের প্রকার অজানা"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ওয়াই-ফাই এর সাথে সংযোগ করা যায়নি"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" একটি দুর্বল ইন্টারনেট সংযোগ রয়েছে৷"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"সংযোগের অনুমতি দেবেন?"</string>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index c0449e0..94161e7 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -1103,6 +1103,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi nema pristup Internetu"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Dodirnite za opcije"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Prebačeno na: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Kada na uređaju <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu, koristi se <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Moguća je naplata usluge."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Prebačeno iz mreže <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> u <xliff:g id="NEW_NETWORK">%2$s</xliff:g> mrežu"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobilni podaci"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"nepoznata vrsta mreže"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Problem prilikom spajanja na Wi-Fi mrežu"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima lošu internet vezu."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Želite li dozvoliti povezivanje?"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index f4869d6..d68b3ce 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"La Wi-Fi no té accés a Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Toca per veure les opcions"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Actualment en ús: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"El dispositiu utilitza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> en cas que <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tingui accés a Internet. És possible que s\'apliquin càrrecs."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Abans es feia servir la xarxa <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>; ara s\'utilitza <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"dades mòbils"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"una tipus de xarxa desconegut"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No s\'ha pogut connectar a la Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" té una mala connexió a Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Vols permetre la connexió?"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 449b035..e31e5e6 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1126,6 +1126,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi nemá přístup k internetu"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Klepnutím zobrazíte možnosti"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Přechod na síť <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Když síť <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nebude mít přístup k internetu, zařízení použije síť <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Mohou být účtovány poplatky."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Přechod ze sítě <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na síť <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobilní data"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"neznámý typ sítě"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Připojení k síti Wi-Fi se nezdařilo"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" má pomalé připojení k internetu."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Povolit připojení?"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index ca79ce8..9d1c34f 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi har ingen internetadgang"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Tryk for at se valgmuligheder"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Der blev skiftet til <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Enheden benytter <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, når <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ikke har adgang til internettet. Der opkræves muligvis gebyr."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Der blev skiftet fra <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> til <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobildata"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"en ukendt netværkstype"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kunne ikke oprette forbindelse til Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dårlig internetforbindelse."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Vil du tillade denne forbindelse?"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 469a535..04ecee1 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"WLAN hat keinen Internetzugriff"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Für Optionen tippen"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Zu <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> gewechselt"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Auf dem Gerät wird \"<xliff:g id="NEW_NETWORK">%1$s</xliff:g>\" verwendet, wenn über \"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>\" kein Internet verfügbar ist. Eventuell fallen Gebühren an."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Von \"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>\" zu \"<xliff:g id="NEW_NETWORK">%2$s</xliff:g>\" gewechselt"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobile Datennutzung"</item>
+    <item msgid="75483255295529161">"WLAN"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"ein unbekannter Netzwerktyp"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Es konnte keine WLAN-Verbindung hergestellt werden."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" hat eine schlechte Internetverbindung."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Verbindung zulassen?"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 7bd02cd..18f5f27 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Το δίκτυο Wi-Fi δεν έχει πρόσβαση στο διαδίκτυο"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Πατήστε για να δείτε τις επιλογές"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Μετάβαση σε δίκτυο <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Η συσκευή χρησιμοποιεί το δίκτυο <xliff:g id="NEW_NETWORK">%1$s</xliff:g> όταν το δίκτυο <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> δεν έχει πρόσβαση στο διαδίκτυο. Ενδέχεται να ισχύουν χρεώσεις."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Μετάβαση από το δίκτυο <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> στο δίκτυο <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"δεδομένα κινητής τηλεφωνίας"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"άγνωστος τύπος δικτύου"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Δεν είναι δυνατή η σύνδεση στο Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" έχει κακή σύνδεση στο Διαδίκτυο."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Να επιτρέπεται η σύνδεση;"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 0425e33..d908eb7 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi has no Internet access"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Tap for options"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no Internet access. Charges may apply."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobile data"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"an unknown network type"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Couldn\'t connect to Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" has a poor Internet connection."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Allow connection?"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 0425e33..d908eb7 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi has no Internet access"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Tap for options"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no Internet access. Charges may apply."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobile data"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"an unknown network type"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Couldn\'t connect to Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" has a poor Internet connection."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Allow connection?"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 0425e33..d908eb7 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi has no Internet access"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Tap for options"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Switched to <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Device uses <xliff:g id="NEW_NETWORK">%1$s</xliff:g> when <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> has no Internet access. Charges may apply."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Switched from <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> to <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobile data"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"an unknown network type"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Couldn\'t connect to Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" has a poor Internet connection."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Allow connection?"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 0a9fa94..acb3f21 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"La red Wi-Fi no tiene acceso a Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Presiona para ver opciones"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Se cambió a <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"El dispositivo usa <xliff:g id="NEW_NETWORK">%1$s</xliff:g> cuando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tiene acceso a Internet. Es posible que se apliquen cargos."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Se cambió de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"datos móviles"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"un tipo de red desconocido"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No se pudo conectar a la red Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tiene una mala conexión a Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"¿Permitir la conexión?"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index e019c9e..e8e3ad0 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi sin acceso a Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Toca para ver opciones"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Se ha cambiado a <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"El dispositivo utiliza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> cuando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tiene acceso a Internet. Es posible que se apliquen cargos."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Se ha cambiado de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"datos móviles"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"tipo de red desconocido"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No se ha podido establecer conexión con la red Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tiene una conexión inestable a Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"¿Permitir la conexión?"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 72b83fe..1263382 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"WiFi-l pole juurdepääsu Internetile"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Puudutage valikute nägemiseks"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Lülitati võrgule <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Seade kasutab võrku <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, kui võrgul <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> puudub Interneti-ühendus. Rakenduda võivad tasud."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Lülitati võrgult <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> võrgule <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobiilne andmeside"</item>
+    <item msgid="75483255295529161">"WiFi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"tundmatu võrgutüüp"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ei saanud WiFi-ga ühendust"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" on halb Interneti-ühendus."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Kas lubada ühendus?"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 9a24634..0fa4a00 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi konexioa ezin da Internetera konektatu"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Sakatu aukerak ikusteko"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> erabiltzen ari zara orain"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> Internetera konektatzeko gauza ez denean, <xliff:g id="NEW_NETWORK">%1$s</xliff:g> erabiltzen du gailuak. Agian kostuak ordaindu beharko dituzu."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> erabiltzen ari zinen, baina <xliff:g id="NEW_NETWORK">%2$s</xliff:g> erabiltzen ari zara orain"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"datu-konexioa"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"sare mota ezezaguna"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ezin izan da Wi-Fi sarera konektatu"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" Interneteko konexio txarra du."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Konektatzea baimendu nahi diozu?"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 3fde780..d7227d2 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"‏Wi-Fi به اینترنت دسترسی ندارد"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"برای گزینه‌ها ضربه بزنید"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"به <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> تغییر کرد"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"وقتی <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> دسترسی به اینترنت نداشته باشد، دستگاه از <xliff:g id="NEW_NETWORK">%1$s</xliff:g> استفاده می‌کند. ممکن است هزینه‌هایی اعمال شود."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"از <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> به <xliff:g id="NEW_NETWORK">%2$s</xliff:g> تغییر کرد"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"داده شبکه تلفن همراه"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"بلوتوث"</item>
+    <item msgid="5447331121797802871">"اترنت"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"نوع شبکه نامشخص"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"‏اتصال به Wi-Fi ممکن نیست"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" اتصال اینترنتی ضعیفی دارد."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"اتصال مجاز است؟"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 0446fa6..63029ee 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi ei ole yhteydessä internetiin."</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Näytä vaihtoehdot napauttamalla."</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> otettiin käyttöön"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="NEW_NETWORK">%1$s</xliff:g> otetaan käyttöön, kun <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ei voi muodostaa yhteyttä internetiin. Veloitukset ovat mahdollisia."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> poistettiin käytöstä ja <xliff:g id="NEW_NETWORK">%2$s</xliff:g> otettiin käyttöön."</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobiilidata"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"tuntematon verkon tyyppi"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi-yhteyden muodostaminen epäonnistui"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" : huono internetyhteys."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Sallitaanko yhteys?"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index d9d4fef..22b7b38 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Le réseau Wi-Fi ne dispose d\'aucun accès à Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Touchez pour afficher les options"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Passé au réseau <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"L\'appareil utilise <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quand <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> n\'a pas d\'accès à Internet. Des frais peuvent s\'appliquer."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Passé du réseau <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> au <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"données cellulaires"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"RPV"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"un type de réseau inconnu"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossible de se connecter au Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" dispose d\'une mauvaise connexion Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Autoriser la connexion?"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index ebed571..5b99f6a 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Le réseau Wi-Fi ne dispose d\'aucun accès à Internet."</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Appuyez ici pour afficher des options."</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Nouveau réseau : <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"L\'appareil utilise <xliff:g id="NEW_NETWORK">%1$s</xliff:g> lorsque <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> n\'a pas de connexion Internet. Des frais supplémentaires peuvent s\'appliquer."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Ancien réseau : <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>. Nouveau réseau : <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"données mobiles"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"type de réseau inconnu"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossible de se connecter au Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" dispose d\'une mauvaise connexion Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Autoriser la connexion ?"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index b374095..fea76f7 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"A wifi non ten acceso a Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Toca para ver opcións."</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Cambiouse a: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"O dispositivo utiliza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> cando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> non ten acceso a Internet. Pódense aplicar cargos."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Cambiouse de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"datos móbiles"</item>
+    <item msgid="75483255295529161">"wifi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"un tipo de rede descoñecido"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Non se puido conectar coa rede Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ten unha conexión a Internet deficiente."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Queres permitir a conexión?"</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 4ae0966..16cef71 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi ને કોઈ ઇન્ટરનેટ ઍક્સેસ નથી"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"વિકલ્પો માટે ટૅપ કરો"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> પર સ્વિચ કર્યું"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"જ્યારે <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> પાસે કોઈ ઇન્ટરનેટ ઍક્સેસ ન હોય ત્યારે ઉપકરણ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> નો ઉપયોગ કરે છે. શુલ્ક લાગુ થઈ શકે છે."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> પરથી <xliff:g id="NEW_NETWORK">%2$s</xliff:g> પર સ્વિચ કર્યું"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"સેલ્યુલર ડેટા"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"ઇથરનેટ"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"અજાણ્યો નેટવર્ક પ્રકાર"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi સાથે કનેક્ટ કરી શકાયું નથી"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" નબળું ઇન્ટરનેટ કનેક્શન ધરાવે છે."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"કનેક્શનની મંજૂરી આપીએ?"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 0bc5881..6e75f5d 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -295,9 +295,9 @@
     <string name="permlab_sendSms" msgid="7544599214260982981">"SMS संदेश भेजें और देखें"</string>
     <string name="permdesc_sendSms" msgid="7094729298204937667">"ऐप्स  को SMS संदेशों को भेजने देता है. इसके परिणामस्वरूप अप्रत्‍याशित शुल्‍क लागू हो सकते हैं. दुर्भावनापूर्ण ऐप्स  आपकी पुष्टि के बिना संदेश भेजकर आपका धन व्‍यय कर सकते हैं."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"अपने लेख संदेश (SMS या MMS) पढ़ें"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"ऐप्स  को आपके टेबलेट या सिम कार्ड में संग्रहीत SMS संदेश पढ़ने देता है. इससे सामग्री या गोपनीयता पर ध्यान दिए बिना, ऐप्स  सभी SMS संदेश पढ़ सकता है."</string>
-    <string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"ऐप को आपके टीवी या सिम कार्ड पर संग्रहीत SMS संदेशों को पढ़ने की अनुमति देती है. इससे ऐप को सामग्री या गोपनीयता पर ध्‍यान दिए बिना, सभी SMS संदेशों को पढ़ने की अनुमति मिल जाती है."</string>
-    <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"ऐप्स  को आपके फ़ोन या सिम कार्ड में संग्रहीत SMS संदेश पढ़ने देता है. इससे सामग्री या गोपनीयता पर ध्यान दिए बिना, ऐप्स  सभी SMS संदेश पढ़ सकता है."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"ऐप्स  को आपके टेबलेट या सिम कार्ड में संग्रहीत SMS संदेश पढ़ने देता है. इससे सामग्री या निजता पर ध्यान दिए बिना, ऐप्स  सभी SMS संदेश पढ़ सकता है."</string>
+    <string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"ऐप को आपके टीवी या सिम कार्ड पर संग्रहीत SMS संदेशों को पढ़ने की अनुमति देती है. इससे ऐप को सामग्री या निजता पर ध्‍यान दिए बिना, सभी SMS संदेशों को पढ़ने की अनुमति मिल जाती है."</string>
+    <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"ऐप्स  को आपके फ़ोन या सिम कार्ड में संग्रहीत SMS संदेश पढ़ने देता है. इससे सामग्री या निजता पर ध्यान दिए बिना, ऐप्स  सभी SMS संदेश पढ़ सकता है."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"लेख संदेश (WAP) प्राप्त करें"</string>
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"ऐप्स  को WAP संदेशों को प्राप्‍त और संसाधित करने देता है. इस अनुमति में आपको भेजे गए संदेशों की निगरानी आपको दिखाए बिना करने और हटाने की क्षमता शामिल है."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"चल रहे ऐप्स पुनर्प्राप्त करें"</string>
@@ -347,9 +347,9 @@
     <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="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"ऐप्स  को मित्रों या सहकर्मियों के कैलेंडर इवेंट सहित, आपके टेबलेट पर संग्रहीत कैलेंडर इवेंट पढ़ने देता है. इससे गोपनीयता या संवेदनशीलता पर ध्यान दिए बिना, ऐप्स  आपके कैलेंडर डेटा को साझा कर सकता है या सहेज सकता है."</string>
-    <string name="permdesc_readCalendar" product="tv" msgid="3191352452242394196">"ऐप को, मित्रों और सहकर्मियों के कैलेंडर ईवेंट सहित, आपके टीवी पर संग्रहीत सभी कैलेंडर ईवेंट पढ़ने देती है. इससे ऐप को गोपनीयता या संवेदनशीलता पर ध्‍यान दिए बिना, आपका कैलेडर डेटा साझा करने या सहेजने की अनुमति मिल जाती है."</string>
-    <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"ऐप्स  को मित्रों या सहकर्मियों के कैलेंडर इवेंट सहित, आपके फ़ोन पर संग्रहीत कैलेंडर इवेंट पढ़ने देता है. इससे गोपनीयता या संवेदनशीलता पर ध्यान दिए बिना, ऐप्स  आपके कैलेंडर डेटा को साझा कर सकता है या सहेज सकता है."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"ऐप्स  को मित्रों या सहकर्मियों के कैलेंडर इवेंट सहित, आपके टेबलेट पर संग्रहीत कैलेंडर इवेंट पढ़ने देता है. इससे निजता या संवेदनशीलता पर ध्यान दिए बिना, ऐप्स  आपके कैलेंडर डेटा को साझा कर सकता है या सहेज सकता है."</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>
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"वाई-फ़ाई में कोई इंटरनेट ऐक्‍सेस नहीं है"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"विकल्पों के लिए टैप करें"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> पर ले जाया गया"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> में कोई इंटरनेट एक्‍सेस नहीं होने पर डिवाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> का उपयोग करता है. शुल्क लिया जा सकता है."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> से <xliff:g id="NEW_NETWORK">%2$s</xliff:g> पर ले जाया गया"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"सेल्युलर डेटा"</item>
+    <item msgid="75483255295529161">"वाई-फ़ाई"</item>
+    <item msgid="6862614801537202646">"ब्लूटूथ"</item>
+    <item msgid="5447331121797802871">"ईथरनेट"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"अज्ञात नेटवर्क प्रकार"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"वाई-फ़ाई  से कनेक्‍ट नहीं हो सका"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" के पास एक कमज़ोर इंटरनेट कनेक्‍शन है."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"कनेक्शन की अनुमति दें?"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index e7ccf23..700c102 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1101,6 +1101,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi nema pristup internetu"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Dodirnite za opcije"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Prelazak na drugu mrežu: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Kada <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nema pristup internetu, na uređaju se upotrebljava <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Moguća je naplata naknade."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Mreža je promijenjena: <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> &gt; <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobilni podaci"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"nepoznata vrsta mreže"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ne može se spojiti na Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima lošu internetsku vezu."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Dopustiti povezivanje?"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d6fc1c5..0851da8 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"A Wi-Fi-hálózaton nincs internetkapcsolat"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Koppintson a beállítások megjelenítéséhez"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Átváltva erre: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="NEW_NETWORK">%1$s</xliff:g> használata, ha nincs internetkapcsolat <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>-kapcsolaton keresztül. A szolgáltató díjat számíthat fel."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Átváltva <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>-hálózatról erre: <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobiladat"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"ismeretlen hálózati típus"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nem sikerült csatlakozni a Wi-Fi hálózathoz"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" rossz internetkapcsolattal rendelkezik."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Engedélyezi a csatlakozást?"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index fa5a8ec..5c46f23 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi ցանցը համացանցի միացում չունի"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Հպեք՝ ընտրանքները տեսնելու համար"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Անցել է <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ցանցի"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Եթե <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ցանցն ինտերնետ կապ չունի, սարքն անցնում է <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ցանցի: Կարող են վճարներ գանձվել:"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ցանցից անցել է <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ցանցի"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"բջջային տվյալներ"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"ցանցի անհայտ տեսակ"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Չհաջողվեց միանալ Wi-Fi-ին"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ունի թույլ ինտերնետ կապ:"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Թույլատրե՞լ կապը:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 79c868b..6a053cb2 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -116,7 +116,7 @@
     <string name="roamingText5" msgid="7604063252850354350">"Roaming - Sistem Yang Dipilih"</string>
     <string name="roamingText6" msgid="2059440825782871513">"Roaming - Sistem Tersedia"</string>
     <string name="roamingText7" msgid="7112078724097233605">"Mitra Roaming - Alliance"</string>
-    <string name="roamingText8" msgid="5989569778604089291">"Roaming - Mitra Premium"</string>
+    <string name="roamingText8" msgid="5989569778604089291">"Roaming - Partner Premium"</string>
     <string name="roamingText9" msgid="7969296811355152491">"Fungsionalitas Layanan Roaming - Penuh"</string>
     <string name="roamingText10" msgid="3992906999815316417">"Fungsionalitas Layanan Roaming - Sebagian"</string>
     <string name="roamingText11" msgid="4154476854426920970">"Spanduk Roaming Hidup"</string>
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi tidak memiliki akses internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Ketuk untuk melihat opsi"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Dialihkan ke <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Perangkat menggunakan <xliff:g id="NEW_NETWORK">%1$s</xliff:g> jika <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> tidak memiliki akses internet. Tarif mungkin berlaku."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Dialihkan dari <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ke <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"data seluler"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"jenis jaringan yang tidak dikenal"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Tidak dapat tersambung ke Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" memiliki sambungan internet yang buruk."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Izinkan hubungan?"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index ebb1053..d6c69bd 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi netið er ekki með tengingu við internetið"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Ýttu til að sjá valkosti"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Skipt yfir á <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Tækið notar <xliff:g id="NEW_NETWORK">%1$s</xliff:g> þegar <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> er ekki með internetaðgang. Gjöld geta átt við."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Skipt úr <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> yfir í <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"farsímagögn"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"óþekkt tegund netkerfis"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ekki var hægt að tengjast Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" er með lélegt netsamband."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Leyfa tengingu?"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 7267032..10e5fb89 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Connessione Wi-Fi priva di accesso Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Tocca per le opzioni"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Passato a <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Il dispositivo utilizza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> non ha accesso a Internet. Potrebbero essere applicati costi."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Passato da <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> a <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"rete dati"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"tipo di rete sconosciuto"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossibile connettersi alla rete Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ha una connessione Internet debole."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Consentire la connessione?"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 101c6ecc..57f6bd8 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1126,6 +1126,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"‏אין ל-Wi-Fi גישה לאינטרנט"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"הקש לקבלת אפשרויות"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"מעבר אל <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"המכשיר משתמש ברשת <xliff:g id="NEW_NETWORK">%1$s</xliff:g> כשלרשת <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> אין גישה לאינטרנט. עשויים לחול חיובים."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"עבר מרשת <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> לרשת <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"נתונים סלולריים"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"סוג רשת לא מזוהה"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"‏אין אפשרות להתחבר ל-Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" אינו מחובר היטב לאינטרנט."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"האם להתיר את החיבור?"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index c89b86d..19e4055 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fiはインターネットに接続していません"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"タップしてその他のオプションを表示"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"「<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>」に切り替えました"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"端末で「<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>」によるインターネット接続ができない場合に「<xliff:g id="NEW_NETWORK">%1$s</xliff:g>」を使用します。通信料が発生することがあります。"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"「<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>」から「<xliff:g id="NEW_NETWORK">%2$s</xliff:g>」に切り替えました"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"モバイルデータ"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"イーサネット"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"不明なネットワーク タイプ"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fiに接続できませんでした"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" はインターネット接続に問題があります。"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"接続を許可しますか?"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index a018d24..869e036 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi-ს არ აქვს ინტერნეტზე წვდომა"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"შეეხეთ ვარიანტების სანახავად"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"ახლა გამოიყენება <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"თუ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ინტერნეტთან კავშირს დაკარგავს, მოწყობილობის მიერ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> იქნება გამოყენებული, რამაც შეიძლება დამატებითი ხარჯები გამოიწვიოს"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"ახლა გამოიყენება <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> (გამოიყენებოდა <xliff:g id="NEW_NETWORK">%2$s</xliff:g>)"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"მობილური ინტერნეტი"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"უცნობი ტიპის ქსელი"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi-თან დაკავშირება ვერ მოხერხდა"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" აქვს ცუდი ინტერნეტ კავშირი."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"გსურთ კავშირის დაშვება?"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 2417396..749f93a 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi желісінде интернет байланысы жоқ"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Опциялар үшін түртіңіз"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> желісіне ауысты"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Құрылғы <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> желісінде интернетпен байланыс жоғалған жағдайда <xliff:g id="NEW_NETWORK">%1$s</xliff:g> желісін пайдаланады. Деректер ақысы алынуы мүмкін."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> желісінен <xliff:g id="NEW_NETWORK">%2$s</xliff:g> желісіне ауысты"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"ұялы дерек"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"желі түрі белгісіз"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi желісіне қосыла алмады"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" Интернет байланысы нашар."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Қосылуға рұқсат ету керек пе?"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 86669b4..879507c 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1078,6 +1078,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi មិនមានអ៊ិនធឺណិតនោះទេ"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ប៉ះសម្រាប់ជម្រើស"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"បានប្តូរទៅ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"ឧបករណ៍ប្រើ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> នៅពេលដែល <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> គ្មានការតភ្ជាប់អ៊ីនធឺណិត។ អាចគិតប្រាក់លើការប្រើប្រាស់ទិន្នន័យ។"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"បានប្តូរពី <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ទៅ <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"ទិន្នន័យចល័ត"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"ប៊្លូធូស"</item>
+    <item msgid="5447331121797802871">"អ៊ីសឺរណិត"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"ប្រភេទបណ្តាញមិនស្គាល់"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"មិន​​អាច​តភ្ជាប់​វ៉ាយហ្វាយ"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" មាន​ការ​តភ្ជាប់​អ៊ីនធឺណិត​មិន​ល្អ។"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"អនុញ្ញាត​ភ្ជាប់?"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 2eae59c..8fb0fb5 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"ವೈ-ಫೈ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶ ಹೊಂದಿಲ್ಲದಿರುವಾಗ, ಸಾಧನವು <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ಬಳಸುತ್ತದೆ. ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ರಿಂದ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"ಸೆಲ್ಯುಲರ್ ಡೇಟಾ"</item>
+    <item msgid="75483255295529161">"ವೈ-ಫೈ"</item>
+    <item msgid="6862614801537202646">"ಬ್ಲೂಟೂತ್‌"</item>
+    <item msgid="5447331121797802871">"ಇಥರ್ನೆಟ್"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"ಅಪರಿಚಿತ ನೆಟ್‌ವರ್ಕ್ ಪ್ರಕಾರ"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ವೈ-ಫೈ ಗೆ ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ಕಳಪೆ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿದೆ."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"ಸಂಪರ್ಕವನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8810bf9..ebed036 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi가 인터넷에 연결되어 있지 않습니다."</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"탭하여 옵션 보기"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>(으)로 전환"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>이(가) 인터넷에 연결되지 않는 경우 기기에서 <xliff:g id="NEW_NETWORK">%1$s</xliff:g>을(를) 사용합니다. 요금이 부과될 수 있습니다."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>에서 <xliff:g id="NEW_NETWORK">%2$s</xliff:g>(으)로 전환"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"모바일 데이터"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"블루투스"</item>
+    <item msgid="5447331121797802871">"이더넷"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"알 수 없는 네트워크 유형"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi에 연결할 수 없습니다"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 인터넷 연결 상태가 좋지 않습니다."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"연결을 허용하시겠습니까?"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 53ada58..d4d832a 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi тармагы Интернетке туташпай турат"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Параметрлерди ачуу үчүн таптап коюңуз"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> тармагына которуштурулду"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> тармагы Интернетке туташпай турганда, түзмөгүңүз <xliff:g id="NEW_NETWORK">%1$s</xliff:g> тармагын колдонот. Акы алынышы мүмкүн."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> дегенден <xliff:g id="NEW_NETWORK">%2$s</xliff:g> тармагына которуштурулду"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"мобилдик дайындар"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"белгисиз тармак түрү"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi менен туташуу түзүлбөдү"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" хотспотунун интернет байланышы начар."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Туташууга уруксатпы?"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 569b752..293410f7 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi ບໍ່ມີການເຂົ້າເຖິງອິນເຕີເນັດ"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ແຕະເພື່ອເບິ່ງຕົວເລືອກ"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"ສະຫຼັບໄປໃຊ້ <xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ແລ້ວ"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"ອຸປະກອນຈະໃຊ້ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ເມື່ອ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ. ອາດມີການຮຽກເກັບຄ່າບໍລິການ."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"ສະຫຼັບຈາກ <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ໄປໃຊ້ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ແລ້ວ"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"ຂໍ້ມູນອິນເຕີເນັດມືຖື"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"ອີເທີເນັດ"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"ບໍ່ຮູ້ຈັກປະເພດເຄືອຂ່າຍ"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ບໍ່ສາມາດເຊື່ອມຕໍ່ Wi-Fi ໄດ້"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ມີສັນຍານອິນເຕີເນັດທີ່ບໍ່ດີ."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"​ອະ​ນຸ​ຍາດ​ການ​ເຊື່ອມ​ຕໍ່ຫຼື​ບໍ່?"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 42ef31d..dc5bfe2 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1126,6 +1126,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"„Wi-Fi“ tinkle nėra interneto ryšio"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Palieskite, kad būtų rodomos parinktys."</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Perjungta į tinklą <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Įrenginys naudoja tinklą <xliff:g id="NEW_NETWORK">%1$s</xliff:g> kai tinkle <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nėra interneto ryšio. Gali būti taikomi mokesčiai."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Perjungta iš tinklo <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> į tinklą <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobiliojo ryšio duomenys"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Eternetas"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"nežinomas tinklo tipas"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nepavyko prisijungti prie „Wi-Fi“"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" turi prastą interneto ryšį."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Leisti prisijungti?"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index e632263..3e27b7a 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1101,6 +1101,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi tīklā nav piekļuves internetam."</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Pieskarieties, lai skatītu iespējas."</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Pārslēdzās uz tīklu <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Kad tīklā <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nav piekļuves internetam, ierīcē tiek izmantots tīkls <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Var tikt piemērota maksa."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Pārslēdzās no tīkla <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> uz tīklu <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobilie dati"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"nezināms tīkla veids"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nevarēja izveidot savienojumu ar Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ir slikts interneta savienojums."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Vai atļaut savienojumu?"</string>
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 454e4b6..f2933b7 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -42,4 +42,23 @@
         <item>[ApnSettingV3]Tethered Public Mobile,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,4D4F</item>
     </string-array>
 
+    <!-- Values for GPS configuration (Telus) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>SUPL_HOST=supl.google.com</item>
+        <item>SUPL_PORT=7275</item>
+        <item>XTRA_SERVER_1=http://xtrapath1.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_2=http://xtrapath2.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_3=http://xtrapath3.izatcloud.net/xtra2.bin</item>
+        <item>NTP_SERVER=north-america.pool.ntp.org</item>
+        <item>SUPL_MODE=1</item>
+        <item>SUPL_VER=0x20000</item>
+        <item>LPP_PROFILE=2</item>
+        <item>NMEA_PROVIDER=0</item>
+        <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
+        <item>ERR_ESTIMATE=0</item>
+        <item>INTERMEDIATE_POS=0</item>
+        <item>GPS_LOCK=3</item>
+        <item>SUPL_ES=1</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc302-mnc221/config.xml b/core/res/res/values-mcc302-mnc221/config.xml
index ffc9d6c..28b5545 100644
--- a/core/res/res/values-mcc302-mnc221/config.xml
+++ b/core/res/res/values-mcc302-mnc221/config.xml
@@ -32,4 +32,23 @@
         <item>[ApnSettingV3]Koodo,sp.koodo.com,,,,,,,,,302,221,,DUN,,,true,0,,,,,,,gid,4B</item>
     </string-array>
 
+    <!-- Values for GPS configuration (Telus) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>SUPL_HOST=supl.google.com</item>
+        <item>SUPL_PORT=7275</item>
+        <item>XTRA_SERVER_1=http://xtrapath1.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_2=http://xtrapath2.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_3=http://xtrapath3.izatcloud.net/xtra2.bin</item>
+        <item>NTP_SERVER=north-america.pool.ntp.org</item>
+        <item>SUPL_MODE=1</item>
+        <item>SUPL_VER=0x20000</item>
+        <item>LPP_PROFILE=2</item>
+        <item>NMEA_PROVIDER=0</item>
+        <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
+        <item>ERR_ESTIMATE=0</item>
+        <item>INTERMEDIATE_POS=0</item>
+        <item>GPS_LOCK=3</item>
+        <item>SUPL_ES=1</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc302-mnc370/config.xml b/core/res/res/values-mcc302-mnc370/config.xml
index 5e7e8bc..ec402fb 100644
--- a/core/res/res/values-mcc302-mnc370/config.xml
+++ b/core/res/res/values-mcc302-mnc370/config.xml
@@ -43,4 +43,23 @@
         <item>302780</item>
     </string-array>
 
+  <!-- Values for GPS configuration (Rogers) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>SUPL_HOST=supl.google.com</item>
+        <item>SUPL_PORT=7275</item>
+        <item>XTRA_SERVER_1=http://xtrapath1.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_2=http://xtrapath2.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_3=http://xtrapath3.izatcloud.net/xtra2.bin</item>
+        <item>NTP_SERVER=north-america.pool.ntp.org</item>
+        <item>SUPL_MODE=1</item>
+        <item>SUPL_VER=0x20000</item>
+        <item>LPP_PROFILE=2</item>
+        <item>NMEA_PROVIDER=0</item>
+        <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
+        <item>ERR_ESTIMATE=0</item>
+        <item>INTERMEDIATE_POS=0</item>
+        <item>GPS_LOCK=3</item>
+        <item>SUPL_ES=1</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc302-mnc610/config.xml b/core/res/res/values-mcc302-mnc610/config.xml
index 81cec96..73604a3 100644
--- a/core/res/res/values-mcc302-mnc610/config.xml
+++ b/core/res/res/values-mcc302-mnc610/config.xml
@@ -27,4 +27,22 @@
     -->
     <integer name="config_mobile_mtu">1428</integer>
 
+    <!-- Values for GPS configuration (Bell) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>SUPL_HOST=supl.google.com</item>
+        <item>SUPL_PORT=7275</item>
+        <item>XTRA_SERVER_1=http://xtrapath1.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_2=http://xtrapath2.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_3=http://xtrapath3.izatcloud.net/xtra2.bin</item>
+        <item>NTP_SERVER=north-america.pool.ntp.org</item>
+        <item>SUPL_MODE=1</item>
+        <item>SUPL_VER=0x20000</item>
+        <item>LPP_PROFILE=2</item>
+        <item>NMEA_PROVIDER=0</item>
+        <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
+        <item>ERR_ESTIMATE=0</item>
+        <item>INTERMEDIATE_POS=0</item>
+        <item>GPS_LOCK=3</item>
+        <item>SUPL_ES=1</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-mcc302-mnc640/config.xml b/core/res/res/values-mcc302-mnc640/config.xml
index 706570c..8597c65 100644
--- a/core/res/res/values-mcc302-mnc640/config.xml
+++ b/core/res/res/values-mcc302-mnc640/config.xml
@@ -22,4 +22,23 @@
     <string-array translatable="false" name="config_operatorConsideredNonRoaming">
         <item>302</item>
     </string-array>
+
+    <!-- Values for GPS configuration (Bell) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>SUPL_HOST=supl.google.com</item>
+        <item>SUPL_PORT=7275</item>
+        <item>XTRA_SERVER_1=http://xtrapath1.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_2=http://xtrapath2.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_3=http://xtrapath3.izatcloud.net/xtra2.bin</item>
+        <item>NTP_SERVER=north-america.pool.ntp.org</item>
+        <item>SUPL_MODE=1</item>
+        <item>SUPL_VER=0x20000</item>
+        <item>LPP_PROFILE=2</item>
+        <item>NMEA_PROVIDER=0</item>
+        <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
+        <item>ERR_ESTIMATE=0</item>
+        <item>INTERMEDIATE_POS=0</item>
+        <item>GPS_LOCK=3</item>
+        <item>SUPL_ES=1</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-mcc302-mnc720/config.xml b/core/res/res/values-mcc302-mnc720/config.xml
index dcfa5c5..8b4ed30 100644
--- a/core/res/res/values-mcc302-mnc720/config.xml
+++ b/core/res/res/values-mcc302-mnc720/config.xml
@@ -45,4 +45,23 @@
         <item>302780</item>
     </string-array>
 
+  <!-- Values for GPS configuration (Rogers) -->
+    <string-array translatable="false" name="config_gpsParameters">
+        <item>SUPL_HOST=supl.google.com</item>
+        <item>SUPL_PORT=7275</item>
+        <item>XTRA_SERVER_1=http://xtrapath1.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_2=http://xtrapath2.izatcloud.net/xtra2.bin</item>
+        <item>XTRA_SERVER_3=http://xtrapath3.izatcloud.net/xtra2.bin</item>
+        <item>NTP_SERVER=north-america.pool.ntp.org</item>
+        <item>SUPL_MODE=1</item>
+        <item>SUPL_VER=0x20000</item>
+        <item>LPP_PROFILE=2</item>
+        <item>NMEA_PROVIDER=0</item>
+        <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
+        <item>ERR_ESTIMATE=0</item>
+        <item>INTERMEDIATE_POS=0</item>
+        <item>GPS_LOCK=3</item>
+        <item>SUPL_ES=1</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values-mcc310-mnc160/config.xml b/core/res/res/values-mcc310-mnc160/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc160/config.xml
+++ b/core/res/res/values-mcc310-mnc160/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc200/config.xml b/core/res/res/values-mcc310-mnc200/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc200/config.xml
+++ b/core/res/res/values-mcc310-mnc200/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc210/config.xml b/core/res/res/values-mcc310-mnc210/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc210/config.xml
+++ b/core/res/res/values-mcc310-mnc210/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc220/config.xml b/core/res/res/values-mcc310-mnc220/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc220/config.xml
+++ b/core/res/res/values-mcc310-mnc220/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc230/config.xml b/core/res/res/values-mcc310-mnc230/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc230/config.xml
+++ b/core/res/res/values-mcc310-mnc230/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc240/config.xml b/core/res/res/values-mcc310-mnc240/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc240/config.xml
+++ b/core/res/res/values-mcc310-mnc240/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc250/config.xml b/core/res/res/values-mcc310-mnc250/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc250/config.xml
+++ b/core/res/res/values-mcc310-mnc250/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc260/config.xml
+++ b/core/res/res/values-mcc310-mnc260/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc270/config.xml b/core/res/res/values-mcc310-mnc270/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc270/config.xml
+++ b/core/res/res/values-mcc310-mnc270/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc300/config.xml b/core/res/res/values-mcc310-mnc300/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc300/config.xml
+++ b/core/res/res/values-mcc310-mnc300/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc310/config.xml b/core/res/res/values-mcc310-mnc310/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc310/config.xml
+++ b/core/res/res/values-mcc310-mnc310/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc490/config.xml b/core/res/res/values-mcc310-mnc490/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc490/config.xml
+++ b/core/res/res/values-mcc310-mnc490/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc530/config.xml b/core/res/res/values-mcc310-mnc530/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc530/config.xml
+++ b/core/res/res/values-mcc310-mnc530/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc580/config.xml b/core/res/res/values-mcc310-mnc580/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc580/config.xml
+++ b/core/res/res/values-mcc310-mnc580/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc590/config.xml b/core/res/res/values-mcc310-mnc590/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc590/config.xml
+++ b/core/res/res/values-mcc310-mnc590/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc640/config.xml b/core/res/res/values-mcc310-mnc640/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc640/config.xml
+++ b/core/res/res/values-mcc310-mnc640/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc660/config.xml b/core/res/res/values-mcc310-mnc660/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc660/config.xml
+++ b/core/res/res/values-mcc310-mnc660/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc800/config.xml b/core/res/res/values-mcc310-mnc800/config.xml
index 2cae7cc..5a6a84b 100644
--- a/core/res/res/values-mcc310-mnc800/config.xml
+++ b/core/res/res/values-mcc310-mnc800/config.xml
@@ -32,9 +32,4 @@
 
     <!-- Flag specifying whether VoLTE TTY is supported -->
     <bool name="config_carrier_volte_tty_supported">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 875849a..78405cd 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi нема пристап на интернет"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Допрете за опции"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Префрлено на <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Уредот користи <xliff:g id="NEW_NETWORK">%1$s</xliff:g> кога <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> нема пристап до интернет. Може да се наплатат трошоци."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Префрлено од <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> на <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"мобилен интернет"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Етернет"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"непознат тип мрежа"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не можеше да се поврзе со Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" има слаба конекција на интернет."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Дозволете поврзување?"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index e914a8c..3fdbf3a 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi-യിൽ ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല."</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> എന്നതിലേക്ക് മാറി"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> നെറ്റ്‌വർക്കിന് ഇന്റർനെറ്റ് ആക്സസ്സ് ഇല്ലാത്തപ്പോൾ ഉപകരണം <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ഉപയോഗിക്കുന്നു. നിരക്കുകൾ ബാധകമായേക്കാം."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> നെറ്റ്‌വർക്കിൽ നിന്ന് <xliff:g id="NEW_NETWORK">%2$s</xliff:g> നെറ്റ്‌വർക്കിലേക്ക് മാറി"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"സെല്ലുലാർ ഡാറ്റ"</item>
+    <item msgid="75483255295529161">"വൈഫൈ"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"ഇതര്‍നെറ്റ്"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"തിരിച്ചറിയാനാകാത്ത ഒരു നെറ്റ്‌വർക്ക് തരം"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi-ലേക്ക് കണക്‌റ്റുചെയ്യാൻ കഴിഞ്ഞില്ല"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" മോശം ഇന്റർനെറ്റ് കണക്ഷനാണുള്ളത്."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"കണക്ഷൻ അനുവദിക്കണോ?"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 80a2b32..9ecb7538 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi-д интернет холболт байхгүй байна"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Сонголт хийхийн тулд товшино уу"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> руу шилжүүлсэн"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> интернэт холболтгүй үед төхөөрөмж <xliff:g id="NEW_NETWORK">%1$s</xliff:g>-г ашигладаг. Төлбөр гарч болзошгүй."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>-с <xliff:g id="NEW_NETWORK">%2$s</xliff:g> руу шилжүүлсэн"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"мобайл дата"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Этернэт"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"сүлжээний тодорхойгүй төрөл"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi-д холбогдож чадсангүй"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" Интернет холболт муу байна."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Холболтыг зөвшөөрөх үү?"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 67b0a1c..c00a053 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"वाय-फाय मध्‍ये इंटरनेट प्रवेश नाही"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"पर्यायांसाठी टॅप करा"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> वर स्विच केले"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> कडे इंटरनेट प्रवेश नसताना डिव्हाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> वापरतो. शुल्क लागू शकतील."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> पासून <xliff:g id="NEW_NETWORK">%2$s</xliff:g> पर्यंत स्विच केले"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"मोबाइल डेटा"</item>
+    <item msgid="75483255295529161">"वाय-फाय"</item>
+    <item msgid="6862614801537202646">"ब्लूटुथ"</item>
+    <item msgid="5447331121797802871">"इथरनेट"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"अज्ञात नेटवर्क प्रकार"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"वाय-फाय ला कनेक्ट करू शकलो नाही"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" खराब इंटरनेट कनेक्शन आहे."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"कनेक्शनला अनुमती द्यायची?"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 99bd9f6..e975a6a 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi tiada akses Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Ketik untuk mendapatkan pilihan"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Beralih kepada <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Peranti menggunakan <xliff:g id="NEW_NETWORK">%1$s</xliff:g> apabila <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> tiada akses Internet. Bayaran mungkin dikenakan."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Beralih daripada <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> kepada <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"data selular"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"jenis rangkaian tidak diketahui"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Tidak boleh menyambung kepada Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" mempunyai sambungan internet yang kurang baik."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Benarkan sambungan?"</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 07394ef..349bc04 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"ဝိုင်-ဖို်ငတွင် အင်တာနက် ဝင်ရောက်သုံးခွင့် မရှိပါ"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"အခြားရွေးချယ်စရာများကိုကြည့်ရန် တို့ပါ"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> သို့ ပြောင်းလိုက်ပြီ"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"စက်ပစ္စည်းသည် <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ဖြင့် အင်တာနက် အသုံးမပြုနိုင်သည့်အချိန်တွင် <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ကို သုံးပါသည်။ ဒေတာသုံးစွဲခ ကျသင့်နိုင်ပါသည်။"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> မှ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> သို့ ပြောင်းလိုက်ပြီ"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"ဆယ်လူလာဒေတာ"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"ဘလူးတုသ်"</item>
+    <item msgid="5447331121797802871">"အီသာနက်"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"အမည်မသိကွန်ရက်အမျိုးအစား"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ဝိုင်ဖိုင်ကိုချိတ်ဆက်မရပါ"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" အင်တာနက် ဆက်သွယ်မှု ကောင်းကောင်းမရှိပါ"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"ချိတ်ဆက်မှုကို ခွင့်ပြုမလား?"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 5c65e0d..8180ab5 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi har ikke Internett-tilgang"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Trykk for å få alternativer"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Byttet til <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Enheten bruker <xliff:g id="NEW_NETWORK">%1$s</xliff:g> når <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ikke har Internett-tilgang. Avgifter kan påløpe."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Byttet fra <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> til <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobildata"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"en ukjent nettverkstype"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kan ikke koble til Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dårlig Internett-tilkobling."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Vil du tillat tilkoblingen?"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index c5ad97a..c486b13 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1082,6 +1082,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi मा इन्टरनेट पहुँच छैन"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"विकल्पहरूका लागि ट्याप गर्नुहोस्"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> मा बदल्नुहोस्"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> मा इन्टरनेट माथिको पहुँच नहुँदा यन्त्रले <xliff:g id="NEW_NETWORK">%1$s</xliff:g> को प्रयोग गर्दछ। शुल्कहरू लागू हुन सक्छन्।"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> बाट <xliff:g id="NEW_NETWORK">%2$s</xliff:g> मा परिवर्तन गरियो"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"सेलुलर डेटा"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"ब्लुटुथ"</item>
+    <item msgid="5447331121797802871">"इथरनेट"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"नेटवर्कको कुनै अज्ञात प्रकार"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"वाइ-फाइसँग जडान गर्न सकेन"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" कमजोर इन्टरनेट जडान छ।"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"जडान अनुमति दिने हो?"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 35ec37f..4f7f849 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wifi-netwerk heeft geen internettoegang"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Tik voor opties"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Overgeschakeld naar <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Apparaat gebruikt <xliff:g id="NEW_NETWORK">%1$s</xliff:g> wanneer <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> geen internetverbinding heeft. Er kunnen kosten in rekening worden gebracht."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Overgeschakeld van <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> naar <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobiele data"</item>
+    <item msgid="75483255295529161">"Wifi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"een onbekend netwerktype"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kan geen verbinding maken met wifi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" heeft een slechte internetverbinding."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Verbinding toestaan?"</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index a18fbaa..ded9674 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi ਦੀ ਕੋਈ ਇੰਟਰਨੈਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> \'ਤੇ ਬਦਲੀ ਕੀਤੀ ਗਈ"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ਦੀ ਇੰਟਰਨੈੱਟ \'ਤੇ ਪਹੁੰਚ ਨਾ ਹੋਣ \'ਤੇ ਡੀਵਾਈਸ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਦੀ ਹੈ। ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ਤੋਂ <xliff:g id="NEW_NETWORK">%2$s</xliff:g> \'ਤੇ ਬਦਲੀ ਕੀਤੀ ਗਈ"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"ਸੈਲਿਊਲਰ ਡੈਟਾ"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"ਬਲੂਟੁੱਥ"</item>
+    <item msgid="5447331121797802871">"ਈਥਰਨੈੱਟ"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"ਇੱਕ ਅਗਿਆਤ ਨੈੱਟਵਰਕ ਕਿਸਮ"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ਇਸਦਾ ਇੱਕ ਖ਼ਰਾਬ ਇੰਟਰਨੈਟ ਕਨੈਕਸ਼ਨ ਹੈ।"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"ਕੀ ਕਨੈਕਸ਼ਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index e7d61e2..c7dc5b8 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1126,6 +1126,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Sieć Wi-Fi nie ma dostępu do internetu"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Kliknij, by wyświetlić opcje"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Zmieniono na połączenie typu <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Urządzenie korzysta z połączenia typu <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, gdy <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nie dostępu do internetu. Mogą zostać naliczone opłaty."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Przełączono z połączenia typu <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na <xliff:g id="NEW_NETWORK">%2$s</xliff:g>."</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"komórkowa transmisja danych"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"nieznany typ sieci"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nie można połączyć się z siecią Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ma powolne połączenie internetowe."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Zezwolić na połączenie?"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 94fda0d..d0c875f 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"O Wi-Fi não tem acesso à Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Toque para ver opções"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Alternado para <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"O dispositivo usa <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> não tem acesso à Internet. Cobranças podem ser aplicadas."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Alternado de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> para <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"dados da rede celular"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"um tipo de rede desconhecido"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Não foi possível se conectar a redes Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tem uma conexão de baixa qualidade com a Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Permitir conexão?"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 21daba9..da88bab 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"O Wi-Fi não tem acesso à Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Toque para obter mais opções"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Mudou para <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"O dispositivo utiliza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> não tem acesso à Internet. Podem ser aplicados custos."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Mudou de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> para <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"dados móveis"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"um tipo de rede desconhecido"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Não foi possível ligar a Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tem uma ligação à internet fraca."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Permitir ligação?"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 94fda0d..d0c875f 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"O Wi-Fi não tem acesso à Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Toque para ver opções"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Alternado para <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"O dispositivo usa <xliff:g id="NEW_NETWORK">%1$s</xliff:g> quando <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> não tem acesso à Internet. Cobranças podem ser aplicadas."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Alternado de <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> para <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"dados da rede celular"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"um tipo de rede desconhecido"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Não foi possível se conectar a redes Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tem uma conexão de baixa qualidade com a Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Permitir conexão?"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 2223730..ebad99b9 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1101,6 +1101,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Rețeaua Wi-Fi nu are acces la internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Atingeți pentru opțiuni"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"S-a comutat la <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Dispozitivul folosește <xliff:g id="NEW_NETWORK">%1$s</xliff:g> când <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nu are acces la internet. Se pot aplica taxe."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"S-a comutat de la <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> la <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"date mobile"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"un tip de rețea necunoscut"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nu se poate conecta la Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" are o conexiune la internet slabă."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Permiteți conectarea?"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 8f1d260..f8daf61 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1126,6 +1126,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Сеть Wi-Fi не подключена к Интернету"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Нажмите, чтобы показать варианты."</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Новое подключение: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Устройство использует <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, если подключение к сети <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> недоступно. Может взиматься плата за передачу данных."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Устройство отключено от сети <xliff:g id="NEW_NETWORK">%2$s</xliff:g> и теперь использует <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"мобильные данные"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"неизвестный тип сети"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не удалось подключиться к сети Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" – плохое интернет-соединение."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Разрешить подключение?"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index e04834c..765b3c4 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1078,6 +1078,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi හට අන්තර්ජාල ප්‍රවේශය නැත"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"විකල්ප සඳහා තට්ටු කරන්න"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> වෙත මාරු විය"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"උපාංගය <xliff:g id="NEW_NETWORK">%1$s</xliff:g> <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> සඳහා අන්තර්ජාල ප්‍රවේශය නැති විට භාවිත කරයි. ගාස්තු අදාළ විය හැකිය."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> සිට <xliff:g id="NEW_NETWORK">%2$s</xliff:g> වෙත මාරු විය"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"සෙලියුලර් දත්ත"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"බ්ලූටූත්"</item>
+    <item msgid="5447331121797802871">"ඊතර්නෙට්"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"නොදන්නා ජාල වර්ගයකි"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi වෙත සම්බන්ධ විය නොහැක"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" දුබල අන්තර්ජාල සම්බන්ධතාවයක් ඇත."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"සම්බන්ධතාවයට ඉඩ දෙන්නද?"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 3e2e21a..21a85df 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1126,6 +1126,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Sieť Wi-Fi nemá prístup k internetu"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Klepnutím získate možnosti"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Prepnuté na sieť: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Keď sieť <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nemá prístup k internetu, zariadenie používa sieť <xliff:g id="NEW_NETWORK">%1$s</xliff:g>. Môžu sa účtovať poplatky."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Prepnuté zo siete <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na sieť <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobilné dáta"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"neznámy typ siete"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nepodarilo sa pripojiť k sieti Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" má nekvalitné internetové pripojenie."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Povoliť pripojenie?"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 25df17f..9521cae 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1126,6 +1126,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Omrežje Wi-Fi nima dostopa do interneta"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Dotaknite se za možnosti"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Preklopljeno na omrežje vrste <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Naprava uporabi omrežje vrste <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, ko omrežje vrste <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nima dostopa do interneta. Prenos podatkov se lahko zaračuna posebej."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Preklopljeno z omrežja vrste <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na omrežje vrste <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"prenos podatkov v mobilnih omrežjih"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"neznana vrsta omrežja"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Z omrežjem Wi-Fi se ni mogoče povezati"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima slabo internetno povezavo."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Ali dovolite vzpostavitev povezave?"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index fa88470..cdf46f4 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi nuk ka qasje në internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Trokit për opsionet"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Kaloi te <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Pajisja përdor <xliff:g id="NEW_NETWORK">%1$s</xliff:g> kur <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> nuk ka qasje në internet. Mund të zbatohen tarifa."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Kaloi nga <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> te <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"të dhënat celulare"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Eternet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"një lloj rrjeti i panjohur"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nuk mund të lidhej me Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ka një lidhje të dobët interneti."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Të lejohet lidhja?"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 634a0af..b64393a 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1101,6 +1101,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi нема приступ интернету"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Додирните за опције"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Прешли сте на тип мреже <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Уређај користи тип мреже <xliff:g id="NEW_NETWORK">%1$s</xliff:g> када тип мреже <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> нема приступ интернету. Можда ће се наплаћивати трошкови."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Прешли сте са типа мреже <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> на тип мреже <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"мобилни подаци"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Етернет"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"непознат тип мреже"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Није могуће повезати са Wi-Fi мрежом"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" има лошу интернет везу."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Желите ли да дозволите повезивање?"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index f5bcaf2..48a36b0 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi-nätverket är inte anslutet till internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Tryck för alternativ"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Byte av nätverk till <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="NEW_NETWORK">%1$s</xliff:g> används på enheten när det inte finns internetåtkomst via <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>. Avgifter kan tillkomma."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Byte av nätverk från <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> till <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobildata"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"en okänd nätverkstyp"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Det gick inte att ansluta till Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dålig Internetanslutning."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Tillåt anslutning?"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 4caabba..b910862 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1074,6 +1074,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi haina muunganisho wa intaneti"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Gonga ili upate chaguo"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Sasa inatumia <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Kifaa hutumia <xliff:g id="NEW_NETWORK">%1$s</xliff:g> wakati <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> haina Intaneti. Huenda ukalipishwa."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Imebadilisha mtandao kutoka <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> na sasa inatumia <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"data ya simu za mkononi"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethaneti"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"aina ya mtandao isiyojulikana"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Haikuweza kuunganisha kwa Mtandao-Hewa"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ina muunganisho duni wa Mtandao."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Ungepenga kuruhusu muunganisho?"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 48a1d5d..b3b3dbe 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"வைஃபை இணைய அணுகல் கொண்டிருக்கவில்லை"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"விருப்பங்களுக்கு, தட்டவும்"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>க்கு மாற்றப்பட்டது"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> இல் இணைய அணுகல் இல்லாததால், சாதனமானது <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ஐப் பயன்படுத்துகிறது. கட்டணங்கள் விதிக்கப்படலாம்."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> இலிருந்து <xliff:g id="NEW_NETWORK">%2$s</xliff:g>க்கு மாற்றப்பட்டது"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"செல்லுலார் தரவு"</item>
+    <item msgid="75483255295529161">"வைஃபை"</item>
+    <item msgid="6862614801537202646">"புளூடூத்"</item>
+    <item msgid="5447331121797802871">"ஈத்தர்நெட்"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"தெரியாத நெட்வொர்க் வகை"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"வைஃபை உடன் இணைக்க முடியவில்லை"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" இணைய இணைப்பு மோசமாக உள்ளது."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"இணைப்பை அனுமதிக்கவா?"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 5cd75b2..a883d1b 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fiకి ఇంటర్నెట్ ప్రాప్యత లేదు"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ఎంపికల కోసం నొక్కండి"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>కి మార్చబడింది"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"పరికరం <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>కి ఇంటర్నెట్ ప్రాప్యత లేనప్పుడు <xliff:g id="NEW_NETWORK">%1$s</xliff:g>ని ఉపయోగిస్తుంది. ఛార్జీలు వర్తించవచ్చు."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> నుండి <xliff:g id="NEW_NETWORK">%2$s</xliff:g>కి మార్చబడింది"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"సెల్యులార్ డేటా"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"బ్లూటూత్"</item>
+    <item msgid="5447331121797802871">"ఈథర్‌నెట్"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"తెలియని నెట్‌వర్క్ రకం"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fiకి కనెక్ట్ చేయడం సాధ్యపడలేదు"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" బలహీన ఇంటర్నెట్ కనెక్షన్‌ను కలిగి ఉంది."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"కనెక్షన్‌ని అనుమతించాలా?"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 425ccbd..e1809e4 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi ไม่สามารถเข้าถึงอินเทอร์เน็ต"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"แตะเพื่อดูตัวเลือก"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"เปลี่ยนเป็น <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"อุปกรณ์จะใช้ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> เมื่อ <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ไม่สามารถเข้าถึงอินเทอร์เน็ต อาจมีค่าบริการ"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"เปลี่ยนจาก <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> เป็น <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"เน็ตมือถือ"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"บลูทูธ"</item>
+    <item msgid="5447331121797802871">"อีเทอร์เน็ต"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"ประเภทเครือข่ายที่ไม่รู้จัก"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ไม่สามารถเชื่อมต่อ WiFi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" มีสัญญาณอินเทอร์เน็ตไม่ดี"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"อนุญาตการเชื่อมต่อใช่ไหม"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index fef2575..b699bf6 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Walang access sa Internet ang Wi-Fi"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"I-tap para sa mga opsyon"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Lumipat sa <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Ginagamit ng device ang <xliff:g id="NEW_NETWORK">%1$s</xliff:g> kapag walang access sa Internet ang <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>. Maaaring may mga malapat na singilin."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Lumipat sa <xliff:g id="NEW_NETWORK">%2$s</xliff:g> mula sa <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"cellular data"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"isang hindi kilalang uri ng network"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Hindi makakonekta sa Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ay mayroong mahinang koneksyon sa Internet."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Payagan ang kuneksyon?"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 386a1b3..c6a8be1 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Kablosuz bağlantıda İnternet erişimi yok"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Seçenekler için dokunun"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> ağına geçildi"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ağının İnternet erişimi olmadığında cihaz <xliff:g id="NEW_NETWORK">%1$s</xliff:g> ağını kullanır. Bunun için ödeme alınabilir."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> ağından <xliff:g id="NEW_NETWORK">%2$s</xliff:g> ağına geçildi"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"hücresel veri"</item>
+    <item msgid="75483255295529161">"Kablosuz"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"bilinmeyen ağ türü"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kablosuz bağlantısı kurulamadı"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" İnternet bağlantısı zayıf."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Bağlantıya izin verilsin mi?"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 5433f06..3d90c6a 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1126,6 +1126,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Мережа Wi-Fi не має доступу до Інтернету"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Торкніться, щоб відкрити опції"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Пристрій перейшов на мережу <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Пристрій використовує мережу <xliff:g id="NEW_NETWORK">%1$s</xliff:g>, коли мережа <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> не має доступу до Інтернету. Може стягуватися плата."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Пристрій перейшов з мережі <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> на мережу <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"мобільний трафік"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"Мережа VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"невідомий тип мережі"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не вдалося під’єднатися до мережі Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" має погане з’єднання з Інтернетом."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Дозволити з’єднання?"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 39eb1f2..cf07988 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"‏Wi-Fi کی انٹرنیٹ تک رسائی نہیں ہے"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"اختیارات کیلئے تھپتھپائیں"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> پر سوئچ ہو گیا"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"جب <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> کے پاس انٹرنیٹ تک رسائی نہ ہو تو آلہ <xliff:g id="NEW_NETWORK">%1$s</xliff:g> کو استعمال کرتا ہے۔ چارجز کا اطلاق ہو سکتا ہے۔"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> سے <xliff:g id="NEW_NETWORK">%2$s</xliff:g> پر سوئچ ہو گیا"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"سیلولر ڈیٹا"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"بلوٹوتھ"</item>
+    <item msgid="5447331121797802871">"ایتھرنیٹ"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"نیٹ ورک کی نامعلوم قسم"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"‏Wi-Fi سے مربوط نہیں ہو سکا"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" اس میں ایک کمزور انٹرنیٹ کنکشن ہے۔"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"کنکشن کی اجازت دیں؟"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 99974d1..a495388 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi tarmog‘ida internet aloqasi yo‘q"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Variantlarni ko‘rsatish uchun bosing"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> tarmog‘iga ulanildi"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Qurilma <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> tarmog‘ida internet o‘chganda, <xliff:g id="NEW_NETWORK">%1$s</xliff:g> tarmog‘iga ulaniladi. To‘lov olinishi mumkin."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> tarmog‘idan <xliff:g id="NEW_NETWORK">%2$s</xliff:g> tarmog‘iga o‘tildi"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"mobil internet"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"noma’lum tarmoq turi"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi’ga ulana olmadi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tezligi past Internetga ulangan."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Ulanishga ruxsat berilsinmi?"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 0a9db5f..1915646 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi không có quyền truy cập Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Nhấn để biết tùy chọn"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Đã chuyển sang <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Thiết bị sử dụng <xliff:g id="NEW_NETWORK">%1$s</xliff:g> khi <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> không có quyền truy cập Internet. Bạn có thể phải trả phí."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Đã chuyển từ <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> sang <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"dữ liệu di động"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"Bluetooth"</item>
+    <item msgid="5447331121797802871">"Ethernet"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"loại mạng không xác định"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Không thể kết nối với Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" có kết nối Internet không tốt."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Cho phép kết nối?"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 6ddf364..74e8fde 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"此 WLAN 网络无法访问互联网"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"点按即可查看相关选项"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"已切换至<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"设备会在无法连接到<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>时使用<xliff:g id="NEW_NETWORK">%1$s</xliff:g>(可能需要支付相应的费用)。"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"已从<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>切换至<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"移动数据网络"</item>
+    <item msgid="75483255295529161">"WLAN"</item>
+    <item msgid="6862614801537202646">"蓝牙"</item>
+    <item msgid="5447331121797802871">"以太网"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"未知网络类型"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"无法连接到WLAN"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 互联网连接状况不佳。"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"要允许连接吗?"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 66b8f95..0ed1c2b 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi 並未連接互聯網"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"輕按即可查看選項"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"已切換至<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"當<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g>無法連線至互聯網時,裝置便會切換至<xliff:g id="NEW_NETWORK">%1$s</xliff:g>。可能需要支付額外費用。"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"已從<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>切換至<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"流動數據"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"藍牙"</item>
+    <item msgid="5447331121797802871">"以太網"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"不明網絡類型"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"無法連線至 Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 互聯網連線欠佳。"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"允許連線?"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index ebf48b7..0d4b284 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"Wi-Fi 網路沒有網際網路連線"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"輕觸即可查看選項"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"已切換至<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"裝置會在無法連上 <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> 時切換至<xliff:g id="NEW_NETWORK">%1$s</xliff:g> (可能需要支付相關費用)。"</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"已從 <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> 切換至<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"行動數據"</item>
+    <item msgid="75483255295529161">"Wi-Fi"</item>
+    <item msgid="6862614801537202646">"藍牙"</item>
+    <item msgid="5447331121797802871">"乙太網路"</item>
+    <item msgid="8257233890381651999">"VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"不明的網路類型"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"無法連線至 Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 的網際網路連線狀況不佳。"</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"允許連線?"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 7c3c342..03db375 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1076,6 +1076,17 @@
     <skip />
     <string name="wifi_no_internet" msgid="8451173622563841546">"I-Wi-Fi ayinakho ukufinyelela kwe-inthanethi"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Thepha ukuze uthole izinketho"</string>
+    <string name="network_switch_metered" msgid="4671730921726992671">"Kushintshelwe ku-<xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"Idivayisi isebenzisa i-<xliff:g id="NEW_NETWORK">%1$s</xliff:g> uma i-<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> ingenakho ukufinyelela kwe-inthanethi. Izindleko zingasebenza."</string>
+    <string name="network_switch_metered_toast" msgid="5779283181685974304">"Kushintshelewe kusuka ku-<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> kuya ku-<xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
+  <string-array name="network_switch_type_name">
+    <item msgid="2952042958050315394">"idatha yeselula"</item>
+    <item msgid="75483255295529161">"I-Wi-Fi"</item>
+    <item msgid="6862614801537202646">"I-Bluetooth"</item>
+    <item msgid="5447331121797802871">"I-Ethernet"</item>
+    <item msgid="8257233890381651999">"I-VPN"</item>
+  </string-array>
+    <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"uhlobo olungaziwa lwenethiwekhi"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ayikwazanga ukuxhuma kwi-Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" inoxhumano oluphansi lwe-inthanethi."</string>
     <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Vumela ukuxhumeka?"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 87fad16..71e7977 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2216,18 +2216,18 @@
     <!-- Flag specifying whether VT is available on device -->
     <bool name="config_device_vt_available">false</bool>
 
+    <!-- Flag specifying whether the device will use the "allow_hold_in_ims_call" carrier config
+         option.  When false, the device will support holding of IMS calls, regardless of the
+         carrier config setting. -->
+    <bool name="config_device_respects_hold_carrier_config">true</bool>
+
     <!-- Flag specifying whether VT should be available for carrier: independent of
          carrier provisioning. If false: hard disabled. If true: then depends on carrier
          provisioning, availability etc -->
     <bool name="config_carrier_vt_available">false</bool>
 
     <!-- Flag specifying whether WFC over IMS is available on device -->
-    <bool name="config_device_wfc_ims_available">false</bool>
-
-    <!-- Flag specifying whether WFC over IMS should be available for carrier: independent of
-         carrier provisioning. If false: hard disabled. If true: then depends on carrier
-         provisioning, availability etc -->
-    <bool name="config_carrier_wfc_ims_available">false</bool>
+        <bool name="config_device_wfc_ims_available">false</bool>
 
     <bool name="config_networkSamplingWakesDevice">true</bool>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6b45574..7a0e8ca 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1951,6 +1951,7 @@
   <java-symbol type="anim" name="lock_screen_behind_enter_fade_in" />
   <java-symbol type="anim" name="lock_screen_wallpaper_exit" />
   <java-symbol type="anim" name="launch_task_behind_source" />
+  <java-symbol type="anim" name="wallpaper_open_exit" />
 
   <java-symbol type="bool" name="config_alwaysUseCdmaRssi" />
   <java-symbol type="dimen" name="status_bar_icon_size" />
@@ -2220,9 +2221,9 @@
   <java-symbol type="bool" name="config_carrier_volte_provisioned" />
   <java-symbol type="bool" name="config_carrier_volte_tty_supported" />
   <java-symbol type="bool" name="config_device_vt_available" />
+  <java-symbol type="bool" name="config_device_respects_hold_carrier_config" />
   <java-symbol type="bool" name="config_carrier_vt_available" />
   <java-symbol type="bool" name="config_device_wfc_ims_available" />
-  <java-symbol type="bool" name="config_carrier_wfc_ims_available" />
   <java-symbol type="attr" name="touchscreenBlocksFocus" />
   <java-symbol type="layout" name="resolver_list_with_default" />
   <java-symbol type="string" name="whichApplicationNamed" />
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index aefe1c1..1557dce 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -1214,11 +1214,31 @@
 - from: /r/studio-ui/sdk-manager.html
   to: /studio/intro/update.html?utm_medium=android-studio#sdk-manager
 - from: /r/studio-ui/newjclass.html
-  to: /studio/write/index.html?utm_medium=android-studio
+  to: /studio/write/create-java-class.html?utm_medium=android-studio
 - from: /r/studio-ui/menu-help.html
   to: /studio/intro/index.html?utm_medium=android-studio
 - from: /r/studio-ui/menu-start.html
   to: /training/index.html?utm_medium=android-studio
+- from: /r/studio-ui/run-with-work-profile.html
+  to: /studio/run/index.html#ir-work-profile?utm_medium=android-studio
+- from: /r/studio-ui/am-gpu-debugger.html
+  to: /studio/profile/am-gpu.html?utm_medium=android-studio
+- from: /r/studio-ui/theme-editor.html
+  to: /studio/write/theme-editor.html?utm_medium=android-studio
+- from: /r/studio-ui/translations-editor.html
+  to: /studio/write/translations-editor.html?utm_medium=android-studio
+- from: /r/studio-ui/debug.html
+  to: /studio/debug/index.html?utm_medium=android-studio
+- from: /r/studio-ui/run.html
+  to: /studio/run/index.html?utm_medium=android-studio
+- from: /r/studio-ui/layout-editor.html
+  to: /studio/write/layout-editor.html?utm_medium=android-studio
+- from: /r/studio-ui/project-window.html
+  to: /studio/projects/index.html?utm_medium=android-studio
+- from: /r/studio-ui/lint-inspection-results.html
+  to: /studio/write/lint.html?utm_medium=android-studio
+- from: /r/studio-ui/gradle-console.html
+  to: /studio/run/index.html#gradle-console?utm_medium=android-studio
 
 # Redirects from (removed) N Preview documentation
 - from: /preview/features/afw.html
diff --git a/docs/html/guide/topics/media/camera.jd b/docs/html/guide/topics/media/camera.jd
index c806c88..4995a13d 100644
--- a/docs/html/guide/topics/media/camera.jd
+++ b/docs/html/guide/topics/media/camera.jd
@@ -9,12 +9,7 @@
     <li><a href="#considerations">Considerations</a></li>
     <li><a href="#basics">The Basics</a>
     <li><a href="#manifest">Manifest Declarations</a></li>
-    <li><a href="#intents">Using Existing Camera Apps</a>
-      <ol>
-        <li><a href="#intent-image">Image capture intent</a></li>
-        <li><a href="#intent-video">Video capture intent</a></li>
-        <li><a href="#intent-receive">Receiving camera intent result</a></li>
-      </ol>
+    <li><a href="#camera-apps">Using Existing Camera Apps</a>
     <li><a href="#custom-camera">Building a Camera App</a>
       <ol>
         <li><a href="#detect-camera">Detecting camera hardware</a></li>
@@ -72,7 +67,7 @@
   <li><strong>Quick Picture or Customized Camera</strong> - How will your application use the
 camera? Are you just interested in snapping a quick picture or video clip, or will your application
 provide a new way to use cameras? For a getting a quick snap or clip, consider
-<a href="#intents">Using Existing Camera Apps</a>. For developing a customized camera feature, check
+<a href="#camera-apps">Using Existing Camera Apps</a>. For developing a customized camera feature, check
 out the <a href="#custom-camera">Building a Camera App</a> section.</li>
 
   <li><strong>Storage</strong> - Are the images or videos your application generates intended to be
@@ -122,8 +117,9 @@
 <pre>
 &lt;uses-permission android:name=&quot;android.permission.CAMERA&quot; /&gt;
 </pre>
-  <p class="note"><strong>Note:</strong> If you are using the camera <a href="#intents">via an
-intent</a>, your application does not need to request this permission.</p>
+  <p class="note"><strong>Note:</strong> If you are using the camera <a href="#camera-apps">by
+invoking an existing camera app</a>,
+your application does not need to request this permission.</p>
   </li>
   <li><strong>Camera Features</strong> - Your application must also declare use of camera features,
 for example:
@@ -169,193 +165,17 @@
 </ul>
 
 
-<h2 id="intents">Using Existing Camera Apps</h2>
+<h2 id="camera-apps">Using Existing Camera Apps</h2>
 <p>A quick way to enable taking pictures or videos in your application without a lot of extra code
-is to use an {@link android.content.Intent} to invoke an existing Android camera application. A
-camera intent makes a request to capture a picture or video clip through an existing camera app and
-then returns control back to your application. This section shows you how to capture an image or
-video using this technique.</p>
-
-<p>The procedure for invoking a camera intent follows these general steps:</p>
-
-<ol>
-  <li><strong>Compose a Camera Intent</strong> - Create an {@link android.content.Intent} that
-requests an image or video, using one of these intent types:
-    <ul>
-      <li>{@link android.provider.MediaStore#ACTION_IMAGE_CAPTURE MediaStore.ACTION_IMAGE_CAPTURE} -
-Intent action type for requesting an image from an existing camera application.</li>
-      <li>{@link android.provider.MediaStore#ACTION_VIDEO_CAPTURE MediaStore.ACTION_VIDEO_CAPTURE} -
-Intent action type for requesting a video from an existing camera application. </li>
-    </ul>
-  </li>
-  <li><strong>Start the Camera Intent</strong> - Use the {@link
-android.app.Activity#startActivityForResult(android.content.Intent, int) startActivityForResult()}
-method to execute the camera intent. After you start the intent, the Camera application user
-interface appears on the device screen and the user can take a picture or video.</li>
-  <li><strong>Receive the Intent Result</strong> - Set up an {@link
-android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()} method
-in your application to receive the callback and data from the camera intent. When the user
-finishes taking a picture or video (or cancels the operation), the system calls this method.</li>
-</ol>
-
-
-<h3 id="intent-image">Image capture intent</h3>
-<p>Capturing images using a camera intent is quick way to enable your application to take pictures
-with minimal coding. An image capture intent can include the following extra information:</p>
-
-<ul>
-  <li>{@link android.provider.MediaStore#EXTRA_OUTPUT MediaStore.EXTRA_OUTPUT} - This setting
-requires a {@link android.net.Uri} object specifying a path and file name where you'd like to
-save the picture. This setting is optional but strongly recommended. If you do not specify this
-value, the camera application saves the requested picture in the default location with a default
-name, specified in the returned intent's {@link android.content.Intent#getData() Intent.getData()}
-field.</li>
-</ul>
-
-<p>The following example demonstrates how to construct a image capture intent and execute it.
-The {@code getOutputMediaFileUri()} method in this example refers to the sample code shown in <a
-href= "#saving-media">Saving Media Files</a>.</p>
-
-<pre>
-private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
-private Uri fileUri;
-
-&#64;Override
-public void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    setContentView(R.layout.main);
-
-    // create Intent to take a picture and return control to the calling application
-    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
-
-    fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
-    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name
-
-    // start the image capture Intent
-    startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
-}
-</pre>
-
-<p>When the {@link android.app.Activity#startActivityForResult(android.content.Intent, int)
-startActivityForResult()} method is executed, users see a camera application interface.
-After the user finishes taking a picture (or cancels the operation), the user interface returns to
-your application, and you must intercept the {@link
-android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()}
-method to receive the result of the intent and continue your application execution. For information
-on how to receive the completed intent, see <a href="#intent-receive">Receiving camera intent
-result</a>.</p>
-
-
-<h3 id="intent-video">Video capture intent</h3>
-<p>Capturing video using a camera intent is a quick way to enable your application to take videos
-with minimal coding. A video capture intent can include the following extra information:</p>
-
-<ul>
-  <li>{@link android.provider.MediaStore#EXTRA_OUTPUT MediaStore.EXTRA_OUTPUT} - This setting
-requires a {@link android.net.Uri} specifying a path and file name where you'd like to save the
-video. This setting is optional but strongly recommended. If you do not specify this value, the
-Camera application saves the requested video in the default location with a default name, specified
-in the returned intent's {@link android.content.Intent#getData() Intent.getData()} field.</li>
-  <li>{@link android.provider.MediaStore#EXTRA_VIDEO_QUALITY MediaStore.EXTRA_VIDEO_QUALITY} -
-This value can be 0 for lowest quality and smallest file size or 1 for highest quality and
-larger file size.</li>
-  <li>{@link android.provider.MediaStore#EXTRA_DURATION_LIMIT MediaStore.EXTRA_DURATION_LIMIT} -
-Set this value to limit the length, in seconds, of the video being captured.</li>
-  <li>{@link android.provider.MediaStore#EXTRA_SIZE_LIMIT MediaStore.EXTRA_SIZE_LIMIT} -
-Set this value to limit the file size, in bytes, of the video being captured.
-</li>
-</ul>
-
-<p>The following example demonstrates how to construct a video capture intent and execute it.
-The {@code getOutputMediaFileUri()} method in this example refers to the sample code shown in <a
-href= "#saving-media">Saving Media Files</a>.</p>
-
-<pre>
-private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
-private Uri fileUri;
-
-&#64;Override
-public void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    setContentView(R.layout.main);
-
-    //create new Intent
-    Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
-
-    fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);  // create a file to save the video
-    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);  // set the image file name
-
-    intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // set the video image quality to high
-
-    // start the Video Capture Intent
-    startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
-}
-</pre>
-
-<p>When the {@link
-android.app.Activity#startActivityForResult(android.content.Intent, int)
-startActivityForResult()} method is executed, users see a modified camera application interface.
-After the user finishes taking a video (or cancels the operation), the user interface
-returns to your application, and you must intercept the {@link
-android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()}
-method to receive the result of the intent and continue your application execution. For information
-on how to receive the completed intent, see the next section.</p>
-
-<h3 id="intent-receive">Receiving camera intent result</h3>
-<p>Once you have constructed and executed an image or video camera intent, your application must be
-configured to receive the result of the intent. This section shows you how to intercept the callback
-from a camera intent so your application can do further processing of the captured image or
-video.</p>
-
-<p>In order to receive the result of an intent, you must override the {@link
-android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()} in the
-activity that started the intent. The following example demonstrates how to override {@link
-android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()} to
-capture the result of the <a href="#intent-image">image camera intent</a> or <a
-href="#intent-video">video camera intent</a> examples shown in the previous sections.</p>
-
-<pre>
-private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
-private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
-
-&#64;Override
-protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-    if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
-        if (resultCode == RESULT_OK) {
-            // Image captured and saved to fileUri specified in the Intent
-            Toast.makeText(this, "Image saved to:\n" +
-                     data.getData(), Toast.LENGTH_LONG).show();
-        } else if (resultCode == RESULT_CANCELED) {
-            // User cancelled the image capture
-        } else {
-            // Image capture failed, advise user
-        }
-    }
-
-    if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {
-        if (resultCode == RESULT_OK) {
-            // Video captured and saved to fileUri specified in the Intent
-            Toast.makeText(this, "Video saved to:\n" +
-                     data.getData(), Toast.LENGTH_LONG).show();
-        } else if (resultCode == RESULT_CANCELED) {
-            // User cancelled the video capture
-        } else {
-            // Video capture failed, advise user
-        }
-    }
-}
-</pre>
-
-<p>Once your activity receives a successful result, the captured image or video is available in the
-specified location for your application to access.</p>
-
-
+is to use an {@link android.content.Intent} to invoke an existing Android camera application.
+The details are described in the training lessons
+<a href="{@docRoot}training/camera/photobasics.html">Taking Photos Simply</a> and
+<a href="{@docRoot}training/camera/videobasics.html">Recording Videos Simply</a>.</p>
 
 <h2 id="custom-camera">Building a Camera App</h2>
 <p>Some developers may require a camera user interface that is customized to the look of their
-application or provides special features. Creating a customized camera activity requires more
-code than <a href="#intents">using an intent</a>, but it can provide a more compelling experience
-for your users.</p>
+application or provides special features. Writing your own picture-taking code
+can provide a more compelling experience for your users.</p>
 
 <p><strong> Note: The following guide is for the older, deprecated {@link android.hardware.Camera}
 API. For new or advanced camera applications, the newer {@link android.hardware.camera2} API is
@@ -419,7 +239,7 @@
 <h3 id="access-camera">Accessing cameras</h3>
 <p>If you have determined that the device on which your application is running has a camera, you
 must request to access it by getting an instance of {@link android.hardware.Camera} (unless you
-are using an <a href="#intents">intent to access the camera</a>). </p>
+are using an <a href="camera-apps">intent to access the camera</a>). </p>
 
 <p>To access the primary camera, use the {@link android.hardware.Camera#open() Camera.open()} method
 and be sure to catch any exceptions, as shown in the code below:</p>
diff --git a/docs/html/guide/topics/ui/multi-window.jd b/docs/html/guide/topics/ui/multi-window.jd
index 704391f..dede557 100644
--- a/docs/html/guide/topics/ui/multi-window.jd
+++ b/docs/html/guide/topics/ui/multi-window.jd
@@ -169,7 +169,7 @@
   A root activity's attribute settings apply to all activities
   within its task stack. For example, if the root activity has
   <code>android:resizeableActivity</code> set to true, then all activities
-  in the task stack are resizeable.
+  in the task stack are resizable.
 </p>
 
 <p class="note">
@@ -599,7 +599,7 @@
 
 <p>
   If you disabled multi-window support by setting
-  <code>android:resizableActivity="false"</code>, you should launch your app on
+  <code>android:resizeableActivity="false"</code>, you should launch your app on
   a device running Android 7.0 or higher and attempt to put the app in
   freeform and split-screen modes. Verify that when you do so, the app remains
   in full-screen mode.
diff --git a/docs/html/training/multiple-threads/define-runnable.jd b/docs/html/training/multiple-threads/define-runnable.jd
index 40853d3..84c7bdf 100644
--- a/docs/html/training/multiple-threads/define-runnable.jd
+++ b/docs/html/training/multiple-threads/define-runnable.jd
@@ -23,11 +23,10 @@
 <div class="download-box">
     <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a>
     <p class="filename">ThreadSample.zip</p>
-</div>
-</div>
+</div> <!-- download-box -->
 
-</div>
-</div>
+</div> <!-- tb -->
+</div> <!-- tb-wrapper -->
 
 <p>
     This lesson shows you how to implement a {@link java.lang.Runnable} class, which runs the code
diff --git a/docs/html/work/guide.jd b/docs/html/work/guide.jd
index 30b895b..b2be949 100644
--- a/docs/html/work/guide.jd
+++ b/docs/html/work/guide.jd
@@ -412,6 +412,17 @@
   </li>
 </ol>
 
+<p class="caution"><b>Caution</b>: When running your app with Instant Run in
+Android Studio, attempting to open your app with a Work profile or secondary
+profile will crash your app. To use your app with the Work profile, we
+recommend you create a new <a href="/studio/run/rundebugconfig.html">run
+configuration</a> that includes the <code>--user <var>user_id</var></code> flag,
+specifying the Work profile user ID. You can find the user ID by executing
+<code>adb shell pm list users</code> from command line. For more information,
+see the <a href="/studio/run/index.html#ir-work-profile">Instant Run
+documentation</a>.</p>
+
+
 <h3>Provision a device owner</h3>
 
 <p>
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 5c54324..c386108 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -77,6 +77,8 @@
     private long mProducer;
     private long mFrameAvailableListener;
 
+    private boolean mIsSingleBuffered;
+
     /**
      * Callback interface for being notified that a new stream frame is available.
      */
@@ -130,6 +132,7 @@
      */
     public SurfaceTexture(int texName, boolean singleBufferMode) {
         mCreatorLooper = Looper.myLooper();
+        mIsSingleBuffered = singleBufferMode;
         nativeInit(false, texName, singleBufferMode, new WeakReference<SurfaceTexture>(this));
     }
 
@@ -157,6 +160,7 @@
      */
     public SurfaceTexture(boolean singleBufferMode) {
         mCreatorLooper = Looper.myLooper();
+        mIsSingleBuffered = singleBufferMode;
         nativeInit(true, 0, singleBufferMode, new WeakReference<SurfaceTexture>(this));
     }
 
@@ -378,6 +382,14 @@
         }
     }
 
+    /**
+     * Returns true if the SurfaceTexture is single-buffered
+     * @hide
+     */
+    public boolean isSingleBuffered() {
+        return mIsSingleBuffered;
+    }
+
     private native void nativeInit(boolean isDetached, int texName,
             boolean singleBufferMode, WeakReference<SurfaceTexture> weakSelf)
             throws Surface.OutOfResourcesException;
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index 53d9d03..2e56160 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -97,9 +97,9 @@
 };
 
 struct ClipBase {
-    ClipBase(ClipMode mode)
+    explicit ClipBase(ClipMode mode)
             : mode(mode) {}
-    ClipBase(const Rect& rect)
+    explicit ClipBase(const Rect& rect)
             : mode(ClipMode::Rectangle)
             , rect(rect) {}
     const ClipMode mode;
@@ -112,19 +112,19 @@
 };
 
 struct ClipRect : ClipBase {
-    ClipRect(const Rect& rect)
+    explicit ClipRect(const Rect& rect)
             : ClipBase(rect) {}
 };
 
 struct ClipRectList : ClipBase {
-    ClipRectList(const RectangleList& rectList)
+    explicit ClipRectList(const RectangleList& rectList)
             : ClipBase(ClipMode::RectangleList)
             , rectList(rectList) {}
     RectangleList rectList;
 };
 
 struct ClipRegion : ClipBase {
-    ClipRegion(const SkRegion& region)
+    explicit ClipRegion(const SkRegion& region)
             : ClipBase(ClipMode::Region)
             , region(region) {}
     ClipRegion()
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 2376295..7420112 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -35,7 +35,7 @@
 public:
     // Note that DeferredLayerUpdater assumes it is taking ownership of the layer
     // and will not call incrementRef on it as a result.
-    ANDROID_API DeferredLayerUpdater(Layer* layer);
+    ANDROID_API explicit DeferredLayerUpdater(Layer* layer);
     ANDROID_API ~DeferredLayerUpdater();
 
     ANDROID_API bool setSize(int width, int height) {
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index dedc494..578beaa 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -81,7 +81,7 @@
 
 class FontRenderer {
 public:
-    FontRenderer(const uint8_t* gammaTable);
+    explicit FontRenderer(const uint8_t* gammaTable);
     ~FontRenderer();
 
     void flushLargeCaches(std::vector<CacheTexture*>& cacheTextures);
diff --git a/libs/hwui/GpuMemoryTracker.h b/libs/hwui/GpuMemoryTracker.h
index 851aeae..bfb1bf1 100644
--- a/libs/hwui/GpuMemoryTracker.h
+++ b/libs/hwui/GpuMemoryTracker.h
@@ -52,7 +52,7 @@
     static void onFrameCompleted();
 
 protected:
-    GpuMemoryTracker(GpuObjectType type) : mType(type) {
+    explicit GpuMemoryTracker(GpuObjectType type) : mType(type) {
         ASSERT_GPU_THREAD();
         startTrackingObject();
     }
diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h
index e208b08..a5d9e86 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.h
+++ b/libs/hwui/PropertyValuesAnimatorSet.h
@@ -89,7 +89,7 @@
 
 class PropertyAnimatorSetListener : public AnimationListener {
 public:
-    PropertyAnimatorSetListener(PropertyValuesAnimatorSet* set) : mSet(set) {}
+    explicit PropertyAnimatorSetListener(PropertyValuesAnimatorSet* set) : mSet(set) {}
     virtual void onAnimationFinished(BaseRenderNodeAnimator* animator) override;
 
 private:
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index f3078ce..a65c22c 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -508,7 +508,7 @@
             , mode(PaintUtils::getXfermodeDirect(paint))
             , colorFilter(paint ? paint->getColorFilter() : nullptr) {}
 
-    LayerOp(RenderNode& node)
+    explicit LayerOp(RenderNode& node)
             : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), nullptr, nullptr)
             , layerHandle(node.getLayerHandle())
             , alpha(node.properties().layerProperties().alpha() / 255.0f)
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index cf77cbb..e68fbf4 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -97,7 +97,7 @@
 public:
     class Properties {
     public:
-        Properties(Node* node) : mNode(node) {}
+        explicit Properties(Node* node) : mNode(node) {}
         inline void onPropertyChanged() {
             mNode->onPropertyChanged(this);
         }
@@ -139,7 +139,7 @@
 
     class PathProperties : public Properties {
     public:
-        PathProperties(Node* node) : Properties(node) {}
+        explicit PathProperties(Node* node) : Properties(node) {}
         void syncProperties(const PathProperties& prop) {
             mData = prop.mData;
             onPropertyChanged();
@@ -225,7 +225,7 @@
             float strokeMiterLimit = 4;
             int fillType = 0; /* non-zero or kWinding_FillType in Skia */
         };
-        FullPathProperties(Node* mNode) : Properties(mNode), mTrimDirty(false) {}
+        explicit FullPathProperties(Node* mNode) : Properties(mNode), mTrimDirty(false) {}
         ~FullPathProperties() {
             SkSafeUnref(fillGradient);
             SkSafeUnref(strokeGradient);
@@ -416,7 +416,7 @@
 public:
     class GroupProperties : public Properties {
     public:
-        GroupProperties(Node* mNode) : Properties(mNode) {}
+        explicit GroupProperties(Node* mNode) : Properties(mNode) {}
         struct PrimitiveFields {
             float rotate = 0;
             float pivotX = 0;
@@ -546,7 +546,7 @@
 
 class ANDROID_API Tree : public VirtualLightRefBase {
 public:
-    Tree(Group* rootNode) : mRootNode(rootNode) {
+    explicit Tree(Group* rootNode) : mRootNode(rootNode) {
         mRootNode->setPropertyChangedListener(&mPropertyChangedListener);
     }
 
@@ -583,7 +583,7 @@
 
     class TreeProperties {
     public:
-        TreeProperties(Tree* tree) : mTree(tree) {}
+        explicit TreeProperties(Tree* tree) : mTree(tree) {}
         // Properties that can only be modified by UI thread, therefore sync should
         // only go from UI to RT
         struct NonAnimatableProperties {
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index 6307926..10a1db9 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -30,7 +30,7 @@
 public:
     Paint();
     Paint(const Paint& paint);
-    Paint(const SkPaint& paint);
+    Paint(const SkPaint& paint);  // NOLINT(implicit)
     ~Paint();
 
     Paint& operator=(const Paint& other);
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.h b/libs/hwui/renderstate/OffscreenBufferPool.h
index 73a3392..26d4e36 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.h
+++ b/libs/hwui/renderstate/OffscreenBufferPool.h
@@ -126,7 +126,7 @@
                 : width(OffscreenBuffer::computeIdealDimension(layerWidth))
                 , height(OffscreenBuffer::computeIdealDimension(layerHeight)) {}
 
-        Entry(OffscreenBuffer* layer)
+        explicit Entry(OffscreenBuffer* layer)
                 : layer(layer)
                 , width(layer->texture.width())
                 , height(layer->texture.height()) {
diff --git a/libs/hwui/tests/common/TestScene.h b/libs/hwui/tests/common/TestScene.h
index e3777ca..f6f7c62 100644
--- a/libs/hwui/tests/common/TestScene.h
+++ b/libs/hwui/tests/common/TestScene.h
@@ -52,7 +52,7 @@
 
     class Registrar {
     public:
-        Registrar(const TestScene::Info& info) {
+        explicit Registrar(const TestScene::Info& info) {
             TestScene::registerScene(info);
         }
     private:
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index ad94c96..78e9bc4 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -37,10 +37,10 @@
     EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b))
 
 #define EXPECT_RECT_APPROX_EQ(a, b) \
-    EXPECT_TRUE(MathUtils::areEqual(a.left, b.left) \
-            && MathUtils::areEqual(a.top, b.top) \
-            && MathUtils::areEqual(a.right, b.right) \
-            && MathUtils::areEqual(a.bottom, b.bottom));
+    EXPECT_TRUE(MathUtils::areEqual((a).left, (b).left) \
+            && MathUtils::areEqual((a).top, (b).top) \
+            && MathUtils::areEqual((a).right, (b).right) \
+            && MathUtils::areEqual((a).bottom, (b).bottom));
 
 #define EXPECT_CLIP_RECT(expRect, clipStatePtr) \
         EXPECT_NE(nullptr, (clipStatePtr)) << "Op is unclipped"; \
@@ -91,7 +91,7 @@
     public:
         SignalingDtor()
                 : mSignal(nullptr) {}
-        SignalingDtor(int* signal)
+        explicit SignalingDtor(int* signal)
                 : mSignal(signal) {}
         void setSignal(int* signal) {
             mSignal = signal;
@@ -213,7 +213,7 @@
 
     class TestTask : public renderthread::RenderTask {
     public:
-        TestTask(RtCallback rtCallback)
+        explicit TestTask(RtCallback rtCallback)
                 : rtCallback(rtCallback) {}
         virtual ~TestTask() {}
         virtual void run() override;
diff --git a/libs/hwui/utils/FatVector.h b/libs/hwui/utils/FatVector.h
index 93d37c2..df8cb076 100644
--- a/libs/hwui/utils/FatVector.h
+++ b/libs/hwui/utils/FatVector.h
@@ -53,7 +53,7 @@
     typedef T value_type; // needed to implement std::allocator
     typedef T* pointer; // needed to implement std::allocator
 
-    InlineStdAllocator(Allocation& allocation)
+    explicit InlineStdAllocator(Allocation& allocation)
             : mAllocation(allocation) {}
     InlineStdAllocator(const InlineStdAllocator& other)
             : mAllocation(other.mAllocation) {}
@@ -93,7 +93,7 @@
         this->reserve(SIZE);
     }
 
-    FatVector(size_t capacity) : FatVector() {
+    explicit FatVector(size_t capacity) : FatVector() {
         this->resize(capacity);
     }
 
diff --git a/libs/hwui/utils/LinearAllocator.h b/libs/hwui/utils/LinearAllocator.h
index 34c8c6b..f95a6fe 100644
--- a/libs/hwui/utils/LinearAllocator.h
+++ b/libs/hwui/utils/LinearAllocator.h
@@ -157,7 +157,7 @@
     typedef T value_type; // needed to implement std::allocator
     typedef T* pointer; // needed to implement std::allocator
 
-    LinearStdAllocator(LinearAllocator& allocator)
+    explicit LinearStdAllocator(LinearAllocator& allocator)
             : linearAllocator(allocator) {}
     LinearStdAllocator(const LinearStdAllocator& other)
             : linearAllocator(other.linearAllocator) {}
@@ -170,7 +170,7 @@
     };
     // enable allocators to be constructed from other templated types
     template <class U>
-    LinearStdAllocator(const LinearStdAllocator<U>& other)
+    LinearStdAllocator(const LinearStdAllocator<U>& other)  // NOLINT(implicit)
             : linearAllocator(other.linearAllocator) {}
 
     T* allocate(size_t num, const void* = 0) {
@@ -195,7 +195,7 @@
 template <class T>
 class LsaVector : public std::vector<T, LinearStdAllocator<T>> {
 public:
-    LsaVector(const LinearStdAllocator<T>& allocator)
+    explicit LsaVector(const LinearStdAllocator<T>& allocator)
             : std::vector<T, LinearStdAllocator<T>>(allocator) {}
 };
 
diff --git a/libs/input/SpriteController.h b/libs/input/SpriteController.h
index 905833c..7fc8d6f 100644
--- a/libs/input/SpriteController.h
+++ b/libs/input/SpriteController.h
@@ -214,7 +214,7 @@
         virtual ~SpriteImpl();
 
     public:
-        SpriteImpl(const sp<SpriteController> controller);
+        explicit SpriteImpl(const sp<SpriteController> controller);
 
         virtual void setIcon(const SpriteIcon& icon);
         virtual void setVisible(bool visible);
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 4f2d9fbc..957c2d6 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -441,7 +441,7 @@
                     return;
                 }
                 Parcelable item = resultData.getParcelable(MediaBrowserService.KEY_MEDIA_ITEM);
-                if (!(item instanceof MediaItem)) {
+                if (item != null && !(item instanceof MediaItem)) {
                     cb.onError(mediaId);
                     return;
                 }
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index a811ad0..a19e347 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -91,10 +91,12 @@
     public static final String KEY_MEDIA_ITEM = "media_item";
 
     private static final int RESULT_FLAG_OPTION_NOT_HANDLED = 0x00000001;
+    private static final int RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED = 0x00000002;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag=true, value = { RESULT_FLAG_OPTION_NOT_HANDLED })
+    @IntDef(flag=true, value = { RESULT_FLAG_OPTION_NOT_HANDLED,
+            RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED })
     private @interface ResultFlags { }
 
     private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap<>();
@@ -433,11 +435,9 @@
      * been loaded.
      * </p><p>
      * When the given {@code itemId} is invalid, implementations must call
-     * {@link Result#sendResult result.sendResult} with {@code null}, which will
-     * invoke {@link MediaBrowser.ItemCallback#onError}.
+     * {@link Result#sendResult result.sendResult} with {@code null}.
      * </p><p>
-     * The default implementation calls {@link Result#sendResult result.sendResult}
-     * with {@code null}.
+     * The default implementation will invoke {@link MediaBrowser.ItemCallback#onError}.
      * </p>
      *
      * @param itemId The id for the specific
@@ -445,6 +445,7 @@
      * @param result The Result to send the item to.
      */
     public void onLoadItem(String itemId, Result<MediaBrowser.MediaItem> result) {
+        result.setFlags(RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED);
         result.sendResult(null);
     }
 
@@ -703,6 +704,10 @@
                 new Result<MediaBrowser.MediaItem>(itemId) {
             @Override
             void onResultSent(MediaBrowser.MediaItem item, @ResultFlags int flag) {
+                if ((flag & RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED) != 0) {
+                    receiver.send(-1, null);
+                    return;
+                }
                 Bundle bundle = new Bundle();
                 bundle.putParcelable(KEY_MEDIA_ITEM, item);
                 receiver.send(0, bundle);
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index 98d2fa2..aff101f 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -37,7 +37,7 @@
 // for queued events
 class SoundPoolEvent {
 public:
-    SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
+    explicit SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
         mMsg(msg), mArg1(arg1), mArg2(arg2) {}
     int         mMsg;
     int         mArg1;
diff --git a/media/jni/soundpool/SoundPoolThread.h b/media/jni/soundpool/SoundPoolThread.h
index 9096aeb..7b3e1dd 100644
--- a/media/jni/soundpool/SoundPoolThread.h
+++ b/media/jni/soundpool/SoundPoolThread.h
@@ -40,7 +40,7 @@
  */
 class SoundPoolThread {
 public:
-    SoundPoolThread(SoundPool* SoundPool);
+    explicit SoundPoolThread(SoundPool* SoundPool);
     ~SoundPoolThread();
     void loadSample(int sampleID);
     void quit();
diff --git a/media/mca/filterfw/native/core/gl_frame.h b/media/mca/filterfw/native/core/gl_frame.h
index f2a1ad5..fdbb1f5 100644
--- a/media/mca/filterfw/native/core/gl_frame.h
+++ b/media/mca/filterfw/native/core/gl_frame.h
@@ -38,7 +38,7 @@
     // Create an empty GL frame in the specified GL environment. Note, that the GLFrame does NOT
     // take ownership. The caller must make sure the GLEnv stays valid as long as the GLFrame is
     // alive.
-    GLFrame(GLEnv* gl_env);
+    explicit GLFrame(GLEnv* gl_env);
 
     // Deallocate a GL frame.
     ~GLFrame();
diff --git a/media/mca/filterfw/native/core/native_frame.h b/media/mca/filterfw/native/core/native_frame.h
index 0d335b3..2da557d 100644
--- a/media/mca/filterfw/native/core/native_frame.h
+++ b/media/mca/filterfw/native/core/native_frame.h
@@ -27,7 +27,7 @@
 class NativeFrame {
   public:
     // Create an empty native frame.
-    NativeFrame(int size);
+    explicit NativeFrame(int size);
 
     ~NativeFrame();
 
diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml
index 2db6fb0..31a776c 100644
--- a/packages/PrintSpooler/res/layout/print_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_activity.xml
@@ -16,7 +16,6 @@
 
 <com.android.printspooler.widget.PrintContentView
         xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:printspooler="http://schemas.android.com/apk/res/com.android.printspooler"
     android:id="@+id/options_content"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent">
@@ -28,12 +27,14 @@
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:paddingStart="8dip"
+        android:layout_marginEnd="16dp"
         android:elevation="@dimen/preview_controls_elevation"
         android:background="?android:attr/colorPrimary">
 
         <Spinner
             android:id="@+id/destination_spinner"
-            android:layout_width="@dimen/preview_destination_spinner_width"
+            android:layout_width="wrap_content"
+            android:minWidth="@dimen/preview_destination_spinner_width"
             android:layout_height="wrap_content"
             android:layout_marginTop="4dip"
             android:dropDownWidth="wrap_content"
diff --git a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
index 103c157..0d8a90a 100644
--- a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
+++ b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml
@@ -16,7 +16,8 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
-      android:layout_height="?android:attr/listPreferredItemHeightSmall"
+      android:layout_height="wrap_content"
+      android:minHeight="?android:attr/listPreferredItemHeightSmall"
       style="?android:attr/spinnerItemStyle"
       android:orientation="horizontal"
       android:gravity="start|center_vertical">
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 1d50a24..f688a8e 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -1359,8 +1359,8 @@
         // Page range
         mPageRangeTitle = (TextView) findViewById(R.id.page_range_title);
         mPageRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
-        mPageRangeEditText.setVisibility(View.INVISIBLE);
-        mPageRangeTitle.setVisibility(View.INVISIBLE);
+        mPageRangeEditText.setVisibility(View.GONE);
+        mPageRangeTitle.setVisibility(View.GONE);
         mPageRangeEditText.setOnFocusChangeListener(mSelectAllOnFocusListener);
         mPageRangeEditText.addTextChangedListener(new RangeTextWatcher());
 
@@ -1881,8 +1881,8 @@
                         }
                     } else {
                         mPageRangeEditText.setEnabled(false);
-                        mPageRangeEditText.setVisibility(View.INVISIBLE);
-                        mPageRangeTitle.setVisibility(View.INVISIBLE);
+                        mPageRangeEditText.setVisibility(View.GONE);
+                        mPageRangeTitle.setVisibility(View.GONE);
                     }
                 }
             } else {
@@ -1892,8 +1892,8 @@
                 }
                 mRangeOptionsSpinner.setEnabled(false);
                 mPageRangeEditText.setEnabled(false);
-                mPageRangeEditText.setVisibility(View.INVISIBLE);
-                mPageRangeTitle.setVisibility(View.INVISIBLE);
+                mPageRangeEditText.setVisibility(View.GONE);
+                mPageRangeTitle.setVisibility(View.GONE);
             }
         }
 
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index a31489c..e26d4cb 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -38,7 +38,7 @@
     <string name="bluetooth_disconnecting" msgid="8913264760027764974">"Անջատվում է..."</string>
     <string name="bluetooth_connecting" msgid="8555009514614320497">"Միանում է..."</string>
     <string name="bluetooth_connected" msgid="6038755206916626419">"Միացված է"</string>
-    <string name="bluetooth_pairing" msgid="1426882272690346242">"Զուգավորում..."</string>
+    <string name="bluetooth_pairing" msgid="1426882272690346242">"Զուգակցում..."</string>
     <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Միացված (առանց հեռախոսի)"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Միացված է (առանց մեդիա)"</string>
     <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Միացված է (հաղորդագրությանը մուտք չկա)"</string>
@@ -72,7 +72,7 @@
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Զուգավորել"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"Զուգավորել"</string>
     <string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Չեղարկել"</string>
-    <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Զուգավորում է մուտքի թույլտվությունը դեպի ձեր կոնտակտները և զանգերի պատմությունը, երբ միացված է:"</string>
+    <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Զուգակցում է մուտքի թույլտվությունը դեպի ձեր կոնտակտները և զանգերի պատմությունը, երբ միացված է:"</string>
     <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Չհաջողվեց զուգավորել <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ի հետ:"</string>
     <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Հնարավոր չեղավ զուգավորվել <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ի հետ սխալ PIN-ի կամ անցաբառի պատճառով:."</string>
     <string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Հնարավոր չէ կապ հաստատել  <xliff:g id="DEVICE_NAME">%1$s</xliff:g>-ի հետ:"</string>
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java
deleted file mode 100644
index 4ac461d..0000000
--- a/packages/SettingsLib/tests/src/com/android/settingslib/wifi/AccessPointTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settingslib.wifi;
-
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
-
-import com.android.settingslib.BaseTest;
-import com.android.settingslib.wifi.AccessPoint.AccessPointListener;
-
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
-
-// TODO: Add some coverage
-public class AccessPointTest extends BaseTest {
-
-    private static final String TEST_SSID = "TestSsid";
-    private static final int NETWORK_ID = 0;
-
-    private AccessPointListener mAccessPointListener;
-    private AccessPoint mAccessPoint;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mAccessPointListener = Mockito.mock(AccessPointListener.class);
-
-        WifiConfiguration wifiConfig = new WifiConfiguration();
-        wifiConfig.networkId = NETWORK_ID;
-        wifiConfig.SSID = TEST_SSID;
-
-        mAccessPoint = new AccessPoint(mContext, wifiConfig);
-        mAccessPoint.setListener(mAccessPointListener);
-    }
-
-    public void testOnLevelChanged() {
-        ScanResult result = new ScanResult();
-        result.capabilities = "";
-        result.SSID = TEST_SSID;
-
-        // Give it a level.
-        result.level = WifiTrackerTest.levelToRssi(1);
-        mAccessPoint.update(result);
-        verifyOnLevelChangedCallback(1);
-
-        // Give it a better level.
-        result.level = WifiTrackerTest.levelToRssi(2);
-        mAccessPoint.update(result);
-        verifyOnLevelChangedCallback(1);
-    }
-
-    public void testOnAccessPointChangedCallback() {
-        WifiInfo wifiInfo = Mockito.mock(WifiInfo.class);
-        Mockito.when(wifiInfo.getNetworkId()).thenReturn(NETWORK_ID);
-
-        mAccessPoint.update(wifiInfo, null);
-        verifyOnAccessPointsCallback(1);
-
-        mAccessPoint.update(null, null);
-        verifyOnAccessPointsCallback(2);
-
-        ScanResult result = new ScanResult();
-        result.capabilities = "";
-        result.SSID = TEST_SSID;
-        mAccessPoint.update(result);
-        verifyOnAccessPointsCallback(3);
-    }
-
-    private void verifyOnLevelChangedCallback(int num) {
-        ArgumentCaptor<AccessPoint> accessPoint = ArgumentCaptor.forClass(AccessPoint.class);
-        Mockito.verify(mAccessPointListener, Mockito.atLeast(num))
-                .onLevelChanged(accessPoint.capture());
-        assertEquals(mAccessPoint, accessPoint.getValue());
-    }
-
-    private void verifyOnAccessPointsCallback(int num) {
-        ArgumentCaptor<AccessPoint> accessPoint = ArgumentCaptor.forClass(AccessPoint.class);
-        Mockito.verify(mAccessPointListener, Mockito.atLeast(num))
-                .onAccessPointChanged(accessPoint.capture());
-        assertEquals(mAccessPoint, accessPoint.getValue());
-    }
-
-}
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/src/com/android/settingslib/wifi/WifiTrackerTest.java
deleted file mode 100644
index 479c7be..0000000
--- a/packages/SettingsLib/tests/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settingslib.wifi;
-
-import android.content.Intent;
-import android.net.NetworkInfo;
-import android.net.NetworkInfo.State;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
-import android.net.wifi.WifiSsid;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.util.Log;
-
-import com.android.settingslib.BaseTest;
-import com.android.settingslib.wifi.WifiTracker.Scanner;
-import com.android.settingslib.wifi.WifiTracker.WifiListener;
-
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-public class WifiTrackerTest extends BaseTest {
-
-    private static final String TAG = "WifiTrackerTest";
-
-    private static final String[] TEST_SSIDS = new String[] {
-        "TEST_SSID_1",
-        "TEST_SSID_2",
-        "TEST_SSID_3",
-        "TEST_SSID_4",
-        "TEST_SSID_5",
-    };
-    private static final int NUM_NETWORKS = 5;
-
-    private WifiManager mWifiManager;
-    private WifiListener mWifiListener;
-
-    private WifiTracker mWifiTracker;
-
-    private HandlerThread mWorkerThread;
-    private Looper mLooper;
-    private HandlerThread mMainThread;
-    private Looper mMainLooper;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        mWifiManager = Mockito.mock(WifiManager.class);
-        mWifiListener = Mockito.mock(WifiListener.class);
-        mWorkerThread = new HandlerThread("TestHandlerThread");
-        mWorkerThread.start();
-        mLooper = mWorkerThread.getLooper();
-        mMainThread = new HandlerThread("TestHandlerThread");
-        mMainThread.start();
-        mMainLooper = mMainThread.getLooper();
-        mWifiTracker = new WifiTracker(mContext, mWifiListener, mLooper, true, true, true,
-                mWifiManager, mMainLooper);
-        mWifiTracker.mScanner = mWifiTracker.new Scanner();
-        Mockito.when(mWifiManager.isWifiEnabled()).thenReturn(true);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        StringWriter sw = new StringWriter();
-        PrintWriter pw = new PrintWriter(sw);
-        mWifiTracker.dump(pw);
-        pw.flush();
-        Log.d(TAG, sw.toString());
-        super.tearDown();
-    }
-
-    public void testAccessPointsCallback() {
-        sendScanResultsAndProcess(false);
-
-        Mockito.verify(mWifiListener, Mockito.atLeastOnce()).onAccessPointsChanged();
-    }
-
-    public void testConnectedCallback() {
-        sendConnected();
-        waitForThreads();
-
-        Mockito.verify(mWifiListener, Mockito.atLeastOnce()).onConnectedChanged();
-        assertEquals(true, mWifiTracker.isConnected());
-    }
-
-    public void testWifiStateCallback() {
-        final int TEST_WIFI_STATE = WifiManager.WIFI_STATE_ENABLED;
-
-        Intent i = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
-        i.putExtra(WifiManager.EXTRA_WIFI_STATE, TEST_WIFI_STATE);
-        mWifiTracker.mReceiver.onReceive(mContext, i);
-        waitForThreads();
-
-        ArgumentCaptor<Integer> wifiState = ArgumentCaptor.forClass(Integer.class);
-        Mockito.verify(mWifiListener, Mockito.atLeastOnce())
-                .onWifiStateChanged(wifiState.capture());
-        assertEquals(TEST_WIFI_STATE, (int) wifiState.getValue());
-    }
-
-    public void testScanner() {
-        // TODO: Figure out how to verify more of the Scanner functionality.
-        // Make scans be successful.
-        Mockito.when(mWifiManager.startScan()).thenReturn(true);
-
-        mWifiTracker.mScanner.handleMessage(mWifiTracker.mScanner.obtainMessage(Scanner.MSG_SCAN));
-        Mockito.verify(mWifiManager, Mockito.atLeastOnce()).startScan();
-    }
-
-    public void testNetworkSorting() {
-        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
-        List<ScanResult> scanResults = new ArrayList<ScanResult>();
-        String[] expectedSsids = generateTestNetworks(wifiConfigs, scanResults, true);
-
-        // Tell WifiTracker we are connected now.
-        sendConnected();
-
-        // Send all of the configs and scan results to the tracker.
-        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
-        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
-        sendScanResultsAndProcess(false);
-
-        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
-        assertEquals("Expected number of results", NUM_NETWORKS, accessPoints.size());
-        for (int i = 0; i < NUM_NETWORKS; i++) {
-            assertEquals("Verifying slot " + i, expectedSsids[i], accessPoints.get(i).getSsid());
-        }
-    }
-
-    public void testSavedOnly() {
-        mWifiTracker = new WifiTracker(mContext, mWifiListener, mLooper, true, false, true,
-                mWifiManager, mMainLooper);
-        mWifiTracker.mScanner = mWifiTracker.new Scanner();
-
-        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
-        List<ScanResult> scanResults = new ArrayList<ScanResult>();
-        generateTestNetworks(wifiConfigs, scanResults, true);
-
-        // Tell WifiTracker we are connected now.
-        sendConnected();
-
-        // Send all of the configs and scan results to the tracker.
-        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
-        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
-        sendScanResultsAndProcess(false);
-
-        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
-        // Only expect the first two to come back in the results.
-        assertEquals("Expected number of results", 2, accessPoints.size());
-        assertEquals(TEST_SSIDS[1], accessPoints.get(0).getSsid());
-        assertEquals(TEST_SSIDS[0], accessPoints.get(1).getSsid());
-    }
-
-    /**
-     * This tests the case where Settings runs this on a non-looper thread for indexing.
-     */
-    public void testSavedOnlyNoLooper() {
-        mWifiTracker = new WifiTracker(mContext, mWifiListener, mLooper, true, false, true,
-                mWifiManager,  null);
-        mWifiTracker.mScanner = mWifiTracker.new Scanner();
-
-        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
-        List<ScanResult> scanResults = new ArrayList<ScanResult>();
-        generateTestNetworks(wifiConfigs, scanResults, true);
-
-        // Send all of the configs and scan results to the tracker.
-        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
-        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
-        mWifiTracker.forceUpdate();
-
-        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
-        // Only expect the first two to come back in the results.
-        assertEquals("Expected number of results", 2, accessPoints.size());
-        assertEquals(TEST_SSIDS[1], accessPoints.get(0).getSsid());
-        assertEquals(TEST_SSIDS[0], accessPoints.get(1).getSsid());
-    }
-
-    public void testAvailableOnly() {
-        mWifiTracker = new WifiTracker(mContext, mWifiListener, mLooper, false, true, true,
-                mWifiManager, mMainLooper);
-        mWifiTracker.mScanner = mWifiTracker.new Scanner();
-
-        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
-        List<ScanResult> scanResults = new ArrayList<ScanResult>();
-        String[] expectedSsids = generateTestNetworks(wifiConfigs, scanResults, true);
-
-        // Tell WifiTracker we are connected now.
-        sendConnected();
-
-        // Send all of the configs and scan results to the tracker.
-        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
-        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
-        sendScanResultsAndProcess(false);
-
-        // Expect the last one (sorted order) to be left off since its only saved.
-        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
-        assertEquals("Expected number of results", NUM_NETWORKS - 1, accessPoints.size());
-        for (int i = 0; i < NUM_NETWORKS - 1; i++) {
-            assertEquals("Verifying slot " + i, expectedSsids[i], accessPoints.get(i).getSsid());
-        }
-    }
-
-    public void testNonEphemeralConnected() {
-        mWifiTracker = new WifiTracker(mContext, mWifiListener, mLooper, false, true, true,
-                mWifiManager, mMainLooper);
-        mWifiTracker.mScanner = mWifiTracker.new Scanner();
-
-        List<WifiConfiguration> wifiConfigs = new ArrayList<WifiConfiguration>();
-        List<ScanResult> scanResults = new ArrayList<ScanResult>();
-        generateTestNetworks(wifiConfigs, scanResults, false);
-
-        // Tell WifiTracker we are connected now.
-        sendConnected();
-
-        // Send all of the configs and scan results to the tracker.
-        Mockito.when(mWifiManager.getConfiguredNetworks()).thenReturn(wifiConfigs);
-        Mockito.when(mWifiManager.getScanResults()).thenReturn(scanResults);
-        // Do this twice to catch a bug that was happening in the caching, making things ephemeral.
-        sendScanResultsAndProcess(true);
-
-        List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
-        assertEquals("Expected number of results", NUM_NETWORKS - 1, accessPoints.size());
-        assertFalse("Connection is not ephemeral", accessPoints.get(0).isEphemeral());
-        assertTrue("Connected to wifi", accessPoints.get(0).isActive());
-    }
-
-    public void testEnableResumeScanning() {
-        mWifiTracker.mScanner = null;
-
-        Intent i = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
-        // Make sure disable/enable cycle works with no scanner (no crashing).
-        i.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED);
-        mWifiTracker.mReceiver.onReceive(mContext, i);
-        i.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED);
-        mWifiTracker.mReceiver.onReceive(mContext, i);
-
-        Mockito.when(mWifiManager.isWifiEnabled()).thenReturn(false);
-        i.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED);
-        mWifiTracker.mReceiver.onReceive(mContext, i);
-        // Now enable scanning while wifi is off, it shouldn't start.
-        mWifiTracker.resumeScanning();
-        assertFalse(mWifiTracker.mScanner.isScanning());
-
-        // Turn on wifi and make sure scanning starts.
-        i.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED);
-        mWifiTracker.mReceiver.onReceive(mContext, i);
-        assertTrue(mWifiTracker.mScanner.isScanning());
-    }
-
-    private String[] generateTestNetworks(List<WifiConfiguration> wifiConfigs,
-            List<ScanResult> scanResults, boolean connectedIsEphemeral) {
-        String[] expectedSsids = new String[NUM_NETWORKS];
-
-        // First is just saved;
-        addConfig(wifiConfigs, TEST_SSIDS[0]);
-        // This should come last since its not available.
-        expectedSsids[4] = TEST_SSIDS[0];
-
-        // Second is saved and available.
-        addConfig(wifiConfigs, TEST_SSIDS[1]);
-        addResult(scanResults, TEST_SSIDS[1], 0);
-        // This one is going to have a couple extra results, to verify de-duplication.
-        addResult(scanResults, TEST_SSIDS[1], 2);
-        addResult(scanResults, TEST_SSIDS[1], 1);
-        // This should come second since it is available and saved but not connected.
-        expectedSsids[1] = TEST_SSIDS[1];
-
-        // Third is just available, but higher rssi.
-        addResult(scanResults, TEST_SSIDS[2], 3);
-        // This comes after the next one since it has a lower rssi.
-        expectedSsids[3] = TEST_SSIDS[2];
-
-        // Fourth also just available but with even higher rssi.
-        addResult(scanResults, TEST_SSIDS[3], 4);
-        // This is the highest rssi but not saved so it should be after the saved+availables.
-        expectedSsids[2] = TEST_SSIDS[3];
-
-        // Last is going to be connected.
-        int netId = WifiConfiguration.INVALID_NETWORK_ID;
-        if (!connectedIsEphemeral) {
-            netId = addConfig(wifiConfigs, TEST_SSIDS[4]);
-        }
-        addResult(scanResults, TEST_SSIDS[4], 2);
-        // Setup wifi connection to be this one.
-        WifiInfo wifiInfo = Mockito.mock(WifiInfo.class);
-        Mockito.when(wifiInfo.getSSID()).thenReturn(TEST_SSIDS[4]);
-        Mockito.when(wifiInfo.getNetworkId()).thenReturn(netId);
-        Mockito.when(mWifiManager.getConnectionInfo()).thenReturn(wifiInfo);
-        // This should come first since it is connected.
-        expectedSsids[0] = TEST_SSIDS[4];
-
-        return expectedSsids;
-    }
-
-    private void addResult(List<ScanResult> results, String ssid, int level) {
-        results.add(new ScanResult(WifiSsid.createFromAsciiEncoded(ssid),
-                ssid, ssid, levelToRssi(level), AccessPoint.LOWER_FREQ_24GHZ, 0));
-    }
-
-    public static int levelToRssi(int level) {
-        // Reverse level to rssi calculation based off from WifiManager.calculateSignalLevel.
-        final int MAX_RSSI = -55;
-        final int MIN_RSSI = -100;
-        final int NUM_LEVELS = 4;
-        return level * (MAX_RSSI - MIN_RSSI) / (NUM_LEVELS - 1) + MIN_RSSI;
-    }
-
-    private int addConfig(List<WifiConfiguration> configs, String ssid) {
-        WifiConfiguration config = new WifiConfiguration();
-        config.networkId = configs.size();
-        config.SSID = '"' + ssid + '"';
-        configs.add(config);
-        return config.networkId;
-    }
-
-    private void sendConnected() {
-        NetworkInfo networkInfo = Mockito.mock(NetworkInfo.class);
-        Mockito.when(networkInfo.isConnected()).thenReturn(true);
-        Mockito.when(networkInfo.getState()).thenReturn(State.CONNECTED);
-        Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-        intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
-        mWifiTracker.mReceiver.onReceive(mContext, intent);
-    }
-
-    private void sendScanResultsAndProcess(boolean sendTwice) {
-        Intent i = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
-        mWifiTracker.mReceiver.onReceive(mContext, i);
-        if (sendTwice) {
-            mWifiTracker.mReceiver.onReceive(mContext, i);
-        }
-        waitForThreads();
-    }
-
-    private void waitForThreads() {
-        // Run all processing.
-        mWorkerThread.quitSafely();
-        try {
-            mWorkerThread.join();
-        } catch (InterruptedException e) {
-        }
-        // Send all callbacks.
-        mMainThread.quitSafely();
-        try {
-            mMainThread.join();
-        } catch (InterruptedException e) {
-        }
-    }
-
-}
diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
index 8b07599..9fd80d3 100644
--- a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
+++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
@@ -132,6 +132,7 @@
         if (!getFileForDocId(documentId).delete()) {
             throw new FileNotFoundException("Failed to delete: " + documentId);
         }
+        getContext().getContentResolver().notifyChange(getNotificationUri(), null);
     }
 
     // This is used by BugreportProgressService so that the notification uri shared by
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 02f08c5..ee461b8 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Wys horlosiesekondes op die statusbalk. Sal batterylewe dalk beïnvloed."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Herrangskik Kitsinstellings"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Wys helderheid in Kitsinstellings"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktiveer die verdeling van die skerm deur op te swiep"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktiveer gebaar om skerm te verdeel deur van die Oorsig-knoppie af op te swiep"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimenteel"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Skakel Bluetooth aan?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Jy moet Bluetooth aanskakel om jou sleutelbord aan jou tablet te koppel."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f717ee9..96f5ad8 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"የሰዓት ሰከንዶችን በሁኔታ አሞሌ ውስጥ አሳይ። በባትሪ ዕድሜ ላይ ተጽዕኖ ሊኖርው ይችል ይሆናል።"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ፈጣን ቅንብሮችን ዳግም ያደራጁ"</string>
     <string name="show_brightness" msgid="6613930842805942519">"በፈጣን ቅንብሮች ውስጥ ብሩህነትን አሳይ"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"የተከፈለ ማያ ገጽ ወደ ላይ የማንሸራተት ጣት ምልክትን ያንቁ"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ከአጠቃላይ እይታ አዝራሩ ወደ ላይ በማንሸራተት ወደ የተከፈለ ማያ ገጽ የሚገቡበትን የጣት ምልክት ያንቁ"</string>
     <string name="experimental" msgid="6198182315536726162">"የሙከራ"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ብሉቱዝ ይብራ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"የቁልፍ ሰሌዳዎን ከእርስዎ ጡባዊ ጋር ለማገናኘት በመጀመሪያ ብሉቱዝን ማብራት አለብዎት።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 07af00e..eb5b1c9 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -499,8 +499,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"عرض ثواني الساعة في شريط الحالة. قد يؤثر ذلك في عمر البطارية."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"إعادة ترتيب الإعدادات السريعة"</string>
     <string name="show_brightness" msgid="6613930842805942519">"عرض السطوع في الإعدادات السريعة"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"تمكين إيماءة تقسيم الشاشة بالتمرير السريع لأعلى"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"تمكين الإيماء لإدخال تقسيم الشاشة من خلال التمرير السريع لأعلى من زر النظرة العامة"</string>
     <string name="experimental" msgid="6198182315536726162">"إعدادات تجريبية"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"تشغيل البلوتوث؟"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"لتوصيل لوحة المفاتيح بالجهاز اللوحي، يلزمك تشغيل بلوتوث أولاً."</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index b60618e..c60baaa 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Saatın saniyəsini status panelində göstərin. Batareyaya təsir edə bilər."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Sürətli Ayarları yenidən tənzimləyin"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Sürətli ayarlarda parlaqlılığı göstərin"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Bölünmüş ekran sürüşdürməsi aktiv edin"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Jestlərin icmal düyməsindən yuxarı sürüşdürərək bölünmüş ekrana daxil olmasını aktiv edin"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth aktivləşsin?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Tabletinizlə klaviaturaya bağlanmaq üçün ilk olaraq Bluetooth\'u aktivləşdirməlisiniz."</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 6e2301f..3c84e1d 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Sekunde na satu se prikazuju na statusnoj traci. To može da utiče na trajanje baterije."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Preuredi Brza podešavanja"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Prikaži osvetljenost u Brzim podešavanjima"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Omogući pokret za prevlačenje nagore za podeljeni ekran"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Omogućava pokret za prelazak na podeljeni ekran prevlačenjem nagore od dugmeta Pregled"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentalno"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite li da uključite Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Da biste povezali tastaturu sa tabletom, prvo morate da uključite Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-be-rBY/strings.xml b/packages/SystemUI/res/values-be-rBY/strings.xml
index 9aed31a..e335fac68 100644
--- a/packages/SystemUI/res/values-be-rBY/strings.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings.xml
@@ -497,8 +497,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Паказваць секунды гадзінніка на панэлі стану. Можа паўплываць на рэсурс акумулятара."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Змяніць парадак Хуткіх налад"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Паказваць яркасць у Хуткіх наладах"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Уключ. пераход да рэжыму дзялення экрана правядзеннем уверх"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Уключыць пераход да рэжыму дзялення экрана правядзеннем пальцам уверх ад кнопкі «Агляд»"</string>
     <string name="experimental" msgid="6198182315536726162">"Эксперыментальныя"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Уключыць Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Для падлучэння клавіятуры да планшэта трэба спачатку ўключыць Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 570f0c6..89a776b 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Показване на секундите на часовника в лентата на състоянието. Може да се отрази на живота на батерията."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Пренареждане на бързите настройки"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Показване на яркостта от бързите настройки"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Разделяне на екрана с прекарване на пръст нагоре: Активиране"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Активиране на жеста за влизане в режим на разделен екран чрез прокарване на пръст нагоре от бутона за общ преглед"</string>
     <string name="experimental" msgid="6198182315536726162">"Експериментални"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Да се включи ли Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"За да свържете клавиатурата с таблета си, първо трябва да включите Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 595584e..b40a2c9 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"স্থিতি দন্ডে ঘড়ির সেকেন্ড দেখায়৷ ব্যাটারি লাইফকে প্রভাবিত করতে পারে৷"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"দ্রুত সেটিংসে পুনরায় সাজান"</string>
     <string name="show_brightness" msgid="6613930842805942519">"দ্রুত সেটিংসে উজ্জ্বলতা দেখান"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"উপরের দিকে সোয়াইপ করে বিভক্ত-স্ক্রীনে প্রবেশ করার অঙ্গভঙ্গি সক্ষম করুন"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"\'এক নজরে\' বোতাম থেকে উপরের দিকে সোয়াইপ করে, বিভক্ত-স্ক্রীনে প্রবেশ করতে অঙ্গভঙ্গি সক্ষম করুন"</string>
     <string name="experimental" msgid="6198182315536726162">"পরীক্ষামূলক"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ব্লুটুথ চালু করবেন?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"আপনার ট্যাবলেটের সাথে আপনার কীবোর্ড সংযুক্ত করতে, আপনাকে প্রথমে ব্লুটুথ চালু করতে হবে।"</string>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index 22cdd7d..fce98c7 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -495,8 +495,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Prikaži sekunde na statusnoj traci. Može skratiti trajanje baterije."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Preuredi \"Brze postavke\""</string>
     <string name="show_brightness" msgid="6613930842805942519">"Prikaži osvjetljenje u opciji \"Brze postavke\""</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Omogućiti potez za podjelu ekrana prevlačenjem prema gore"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Uključite pokrete prstima da biste ušli u podijeljeni ekran tako što ćete od dugmeta Pregled prevući prstom prema gore"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentalno"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Želiti li uključiti Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Da povežete tastaturu sa tabletom, prvo morate uključiti Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 7a6b27c..2094aa8 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra els segons del rellotge a la barra d\'estat. Això pot afectar la durada de la bateria."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganitza Configuració ràpida"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostra la brillantor a Configuració ràpida"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Activa el gest per dividir la pantalla en lliscar cap amunt"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Activa el gest per entrar al mode de pantalla dividida en lliscar cap amunt des del botó Visió general"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vols activar el Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Per connectar el teclat amb la tauleta, primer has d\'activar el Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 1e17a6c..24e1c12 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -497,8 +497,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Na stavovém řádku se bude zobrazovat sekundová ručička. Může být ovlivněna výdrž baterie."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Změnit uspořádání Rychlého nastavení"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Zobrazit jas v Rychlém nastavení"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktivovat rozdělenou obrazovku přejetím prstem nahoru"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Umožňuje aktivovat rozdělenou obrazovku přejetím prstem nahoru od tlačítka Přehled."</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentální"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Zapnout Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Chcete-li klávesnici připojit k tabletu, nejdříve musíte zapnout Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 3318fb1..5f3eda8 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statuslinjen. Dette kan påvirke batteriets levetid."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Omarranger Hurtige indstillinger"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i Hurtige indstillinger"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktivér bevægelsen Stryg opad for at dele skærmen"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktivér bevægelse for at dele skærmen ved at stryge opad fra knappen Oversigt"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentel"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå Bluetooth til?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Bluetooth skal være slået til, før du kan knytte dit tastatur til din tablet."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 43a931c..0b332c6 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Uhrsekunden in der Statusleiste anzeigen. Kann sich auf die Akkulaufzeit auswirken."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Schnelleinstellungen neu anordnen"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Helligkeit in den Schnelleinstellungen anzeigen"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Teilen des Bildschirms durch Wischen nach oben aktivieren"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktiviert die Bewegung zum Teilen des Bildschirms, bei der von der Schaltfläche \"Übersicht\" nach oben gewischt wird"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentell"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth aktivieren?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Zum Verbinden von Tastatur und Tablet muss Bluetooth aktiviert sein."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 5e3677d..8a788bf 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Εμφάνιση δευτερολέπτων ρολογιού στη γραμμή κατάστασης. Ενδέχεται να επηρεάσει τη διάρκεια ζωής της μπαταρίας."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Αναδιάταξη Γρήγορων ρυθμίσεων"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Εμφάνιση φωτεινότητας στις Γρήγορες ρυθμίσεις"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ενεργοποίηση κίνησης ολίσθησης επάνω για διαχωρισμό οθόνης"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Ενεργοποίηση κίνησης για μετάβαση σε διαχωρισμό οθόνης μέσω ολίσθησης επάνω από το κουμπί \"Επισκόπηση\""</string>
     <string name="experimental" msgid="6198182315536726162">"Σε πειραματικό στάδιο"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Ενεργοποίηση Bluetooth;"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Για να συνδέσετε το πληκτρολόγιο με το tablet σας, θα πρέπει πρώτα να ενεργοποιήσετε το Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 6ac3c4f..532d02b 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Enable split-screen swipe-up gesture"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Enable gesture to enter split-screen by swiping up from the Overview button"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 6ac3c4f..532d02b 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Enable split-screen swipe-up gesture"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Enable gesture to enter split-screen by swiping up from the Overview button"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 6ac3c4f..532d02b 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Enable split-screen swipe-up gesture"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Enable gesture to enter split-screen by swiping up from the Overview button"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Turn on Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 23c53e1..06dbfd8 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar la duración de la batería."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar la Configuración rápida"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar el brillo en la Configuración rápida"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Habilitar gesto de dedo hacia arriba para dividir pantalla"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Habilita el gesto de deslizar el dedo hacia arriba desde el botón Recientes para acceder al modo de pantalla dividida"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"¿Activar Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar el teclado con la tablet, primero debes activar Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index c800c4a..339a42e 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar a la duración de la batería."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Ajustes rápidos"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Ajustes rápidos"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Habilitar deslizar dedo hacia arriba para dividir pantalla"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Habilita el gesto de deslizar el dedo hacia arriba desde el botón Aplicaciones recientes para acceder al modo de pantalla dividida"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"¿Activar Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para poder conectar tu teclado a tu tablet, debes activar el Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 1ef7a14..960db16 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -47,7 +47,7 @@
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Pööra ekraani automaatselt"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"SUMMUTA"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
-    <string name="status_bar_settings_notifications" msgid="397146176280905137">"Teatised"</string>
+    <string name="status_bar_settings_notifications" msgid="397146176280905137">"Märguanded"</string>
     <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth on jagatud"</string>
     <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Seadista sisestusmeetodeid"</string>
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Füüsiline klaviatuur"</string>
@@ -164,7 +164,7 @@
     <!-- no translation found for accessibility_battery_level_charging (1147587904439319646) -->
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Süsteemiseaded"</string>
-    <string name="accessibility_notifications_button" msgid="4498000369779421892">"Teatised"</string>
+    <string name="accessibility_notifications_button" msgid="4498000369779421892">"Märguanded"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Märguande eemaldamine."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS on lubatud."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS-signaali otsimine."</string>
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Olekuribal kella sekundite kuvamine. See võib mõjutada aku kasutusaega."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Korralda kiirseaded ümber"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Kuva kiirseadetes heledus"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Luba ülespühkimise liigutus ekraani poolitamiseks"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Lubab žesti, mis poolitab ekraani, kui kasutaja pühib üles nupul Ülevaade."</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentaalne"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Kas lülitada Bluetooth sisse?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Klaviatuuri ühendamiseks tahvelarvutiga peate esmalt Bluetoothi sisse lülitama."</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 30b0d22..119cc4a 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Erakutsi erlojuko segundoak egoera-barran. Baliteke bateria gehiago erabiltzea."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Berrantolatu ezarpen bizkorrak"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Erakutsi distira Ezarpen bizkorretan"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Gaitu pantaila zatitzeko keinua hatza gora pasatuta"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Sakatu Ikuspegi nagusia botoia eta gaitu hatza gora pasatuta pantaila zatitzeko keinua"</string>
     <string name="experimental" msgid="6198182315536726162">"Esperimentala"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth eginbidea aktibatu nahi duzu?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Teklatua tabletara konektatzeko, Bluetooth eginbidea aktibatu behar duzu."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 3b246c0..406d6e7 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ثانیه‌های ساعت را در نوار وضعیت نشان می‌دهد. ممکن است بر ماندگاری باتری تأثیر بگذارد."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ترتیب مجدد در تنظیمات سریع"</string>
     <string name="show_brightness" msgid="6613930842805942519">"نمایش روشنایی در تنظیمات سریع"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"فعال کردن تقسیم صفحه با اشاره بالا کشیدن"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"اشاره ورود به تقسیم صفحه با بالا کشیدن صفحه از دکمه نمای کلی را فعال می‌کند"</string>
     <string name="experimental" msgid="6198182315536726162">"آزمایشی"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"بلوتوث روشن شود؟"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"برای مرتبط کردن صفحه‌کلید با رایانه لوحی، ابتدا باید بلوتوث را روشن کنید."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index fe27459..baae281 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Näytä sekunnit tilapalkin kellossa. Tämä voi vaikuttaa akun kestoon."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Järjestä pika-asetukset uudelleen"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Näytä kirkkaus pika-asetuksissa"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Siirry jaetun näytön tilaan pyyhkäisemällä ylöspäin"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Voit siirtyä jaetun näytön tilaan pyyhkäisemällä Viimeisimmät-painikkeesta ylöspäin."</string>
     <string name="experimental" msgid="6198182315536726162">"Kokeellinen"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Otetaanko Bluetooth käyttöön?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Jotta voit yhdistää näppäimistön tablettiisi, sinun on ensin otettava Bluetooth käyttöön."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index fac3e24..b760387 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes sur l\'horloge dans la barre d\'état. Cela peut réduire l\'autonomie de la pile."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser les paramètres rapides"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans les paramètres rapides"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Activer le geste d\'écran partagé en balayant vers le haut"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Activer le geste permettant d\'utiliser l\'écran partagé en balayant l\'écran vers le haut à partir du bouton « Aperçu »"</string>
     <string name="experimental" msgid="6198182315536726162">"Fonctions expérimentales"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Activer Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Pour connecter votre clavier à votre tablette, vous devez d\'abord activer la connectivité Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index a93c3e2..01a2c10 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes dans la barre d\'état. Cela risque de réduire l\'autonomie de la batterie."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser la fenêtre de configuration rapide"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans fenêtre de configuration rapide"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Activer l\'écran partagé en balayant vers le haut"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Activer le geste permettant d\'utiliser l\'écran partagé en balayant l\'écran vers le haut à partir du bouton \"Aperçu\""</string>
     <string name="experimental" msgid="6198182315536726162">"Paramètres expérimentaux"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Activer le Bluetooth ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Pour connecter un clavier à votre tablette, vous devez avoir activé le Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 21154fc..c22dfbe 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra os segundos do reloxo na barra de estado. Pode influír na duración da batería."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Configuración rápida"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Configuración rápida"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Activar pantalla dividida pasando o dedo cara arriba"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Activa o xesto de pasar o dedo cara arriba desde o botón Visión xeral para acceder ao modo de pantalla dividida"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Queres activar o Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teu teclado coa tableta, primeiro tes que activar o Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 02fc8c0..2f64bde 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ઘડિયાળ સેકન્ડ સ્થિતિ બારમાં બતાવો. બૅટરીની આવરદા પર અસર કરી શકે છે."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ઝડપી સેટિંગ્સને ફરીથી ગોઠવો"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ઝડપી સેટિંગ્સમાં તેજ બતાવો"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"સ્પ્લિટ-સ્ક્રીન સ્વાઇપ-અપ હાવભાવ સક્ષમ કરો"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"વિહંગાવલોકન બટનમાંથી સ્વાઇપ કરીને સ્પ્લિટ-સ્ક્રીનમાં દાખલ થવા માટે હાવભાવ સક્ષમ કરો"</string>
     <string name="experimental" msgid="6198182315536726162">"પ્રાયોગિક"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ચાલુ કરવુ છે?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"તમારા ટેબ્લેટ સાથે કીબોર્ડ કનેક્ટ કરવા માટે, તમારે પહેલાં Bluetooth ચાલુ કરવાની જરૂર પડશે."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 9a09266..b55284f 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"स्थिति बार में घड़ी के सेकंड दिखाएं. इससे बैटरी के जीवनकाल पर प्रभाव पड़ सकता है."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"त्वरित सेटिंग को पुन: व्यवस्थित करें"</string>
     <string name="show_brightness" msgid="6613930842805942519">"त्वरित सेटिंग में स्क्रीन की रोशनी दिखाएं"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"ऊपर स्वाइप करके विभाजित स्क्रीन में जाने का जेस्चर सक्षम करें"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"अवलोकन बटन से ऊपर स्वाइप करके स्क्रीन विभाजन में आने का हावभाव सक्षम करें"</string>
     <string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटूथ चालू करें?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"अपने कीबोर्ड को अपने टैबलेट से कनेक्ट करने के लिए, आपको पहले ब्लूटूथ चालू करना होगा."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index f549de9..4dc1781 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Prikazuju se sekunde na satu na traci statusa. Može utjecati na trajanje baterije."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Promijeni raspored Brzih postavki"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Prikaži svjetlinu u Brzim postavkama"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Omogući pokret povlačenja prema gore za podijeljen zaslon"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Omogućivanje pokreta za otvaranje podijeljenog zaslona tako da se od gumba Pregled prstom prijeđe prema gore"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentalno"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite li uključiti Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Da biste povezali tipkovnicu s tabletom, morate uključiti Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 25f436d..88a4183 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -480,7 +480,7 @@
     <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Hotspot"</string>
     <string name="accessibility_managed_profile" msgid="6613641363112584120">"Munkaprofil"</string>
     <string name="tuner_warning_title" msgid="7094689930793031682">"Egyeseknek tetszik, másoknak nem"</string>
-    <string name="tuner_warning" msgid="8730648121973575701">"A Kezelőfelület-hangoló az Android felhasználói felületének szerkesztéséhez és testreszabásához nyújt további megoldásokat. Ezek a kísérleti funkciók változhatnak vagy megsérülhetnek a későbbi kiadásokban,illetve eltűnhetnek azokból. Körültekintően járjon el."</string>
+    <string name="tuner_warning" msgid="8730648121973575701">"A Kezelőfelület-hangoló az Android felhasználói felületének szerkesztéséhez és testreszabásához nyújt további megoldásokat. Ezek a kísérleti funkciók változhatnak vagy megsérülhetnek a későbbi kiadásokban, illetve eltűnhetnek azokból. Körültekintően járjon el."</string>
     <string name="tuner_persistent_warning" msgid="8597333795565621795">"Ezek a kísérleti funkciók változhatnak vagy megsérülhetnek a későbbi kiadásokban, illetve eltűnhetnek azokból. Körültekintően járjon el."</string>
     <string name="got_it" msgid="2239653834387972602">"Értem"</string>
     <string name="tuner_toast" msgid="603429811084428439">"Gratulálunk! A Kezelőfelület-hangolót hozzáadtuk a Beállításokhoz"</string>
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Másodpercek megjelenítése az állapotsor óráján. Ez hatással lehet az akkumulátor üzemidejére."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Gyorsbeállítások átrendezése"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Fényerő megjelenítése a gyorsbeállításokban"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Képernyőfelosztó gyors felfelé csúsztatás engedélyezése"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Kézmozdulat engedélyezése osztott képernyős nézet aktiválásához, ha az Áttekintés gombról felfelé húzza az ujját"</string>
     <string name="experimental" msgid="6198182315536726162">"Kísérleti"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Engedélyezi a Bluetooth-kapcsolatot?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Ha a billentyűzetet csatlakoztatni szeretné táblagépéhez, először engedélyeznie kell a Bluetooth-kapcsolatot."</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index ae66d79..a352497 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Ցույց տալ ժամացույցի վայրկյանները կարգավիճակի տողում: Կարող է ազդել մարտկոցի աշխատանքի ժամանակի վրա:"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Վերադասավորել Արագ կարգավորումները"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Ցույց տալ պայծառությունն Արագ կարգավորումներում"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ակտիվացնել մատը վերև սահեցնելով էկրանը տրոհելու ժեստը"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Միացնել Համատեսք կոճակից մատը դեպի վերև սահեցնելու միջոցով տրոհված էկրանի ռեժիմ անցնելու ժեստը"</string>
     <string name="experimental" msgid="6198182315536726162">"Փորձնական"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Միացնե՞լ Bluetooth-ը:"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Ստեղնաշարը ձեր պլանշետին միացնելու համար նախ անհրաժեշտ է միացնել Bluetooth-ը:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index e2d8166..e69fd20 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Tampilkan detik jam di bilah status. Dapat memengaruhi masa pakai baterai."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Atur Ulang Setelan Cepat"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Tampilkan kecerahan di Setelan Cepat"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktifkan isyarat gesek atas untuk layar terpisah"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktifkan isyarat untuk masuk layar terpisah dengan menggesek tombol Ringkasan ke atas"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Aktifkan Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Untuk menghubungkan keyboard dengan tablet, terlebih dahulu aktifkan Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 4ca3677..71e6eb4 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Sýna sekúndur á klukku í stöðustikunni. Getur haft áhrif á endingu rafhlöðu."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Endurraða flýtistillingum"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Sýna birtustig í flýtistillingum"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Virkja skjáskiptingu með því að strjúka upp"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Virkja skjáskiptingarbendingu með því að strjúka upp frá yfirlitshnappi"</string>
     <string name="experimental" msgid="6198182315536726162">"Tilraunastillingar"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Kveikja á Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Til að geta tengt lyklaborðið við spjaldtölvuna þarftu fyrst að kveikja á Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index e8459ab..cb0c8c8 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra i secondi nell\'orologio nella barra di stato. Ciò potrebbe ridurre la durata della carica della batteria."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Riorganizza Impostazioni rapide"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostra luminosità in Impostazioni rapide"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Attiva Schermo diviso mediante scorrimento verso l\'alto"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Consente di attivare la modalità Schermo diviso scorrendo verso l\'alto dal pulsante Panoramica"</string>
     <string name="experimental" msgid="6198182315536726162">"Sperimentali"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Attivare il Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Per connettere la tastiera al tablet, devi prima attivare il Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 2d740b3..dfc6ee5 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -495,8 +495,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"הצג שניות בשעון בשורת הסטטוס. פעולה זו עשויה להשפיע על אורך חיי הסוללה."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"סידור מחדש של הגדרות מהירות"</string>
     <string name="show_brightness" msgid="6613930842805942519">"הצג בהירות בהגדרות מהירות"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"הפעל מסך מפוצל על ידי תנועת החלקה כלפי מעלה"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"הפעל את התנועה לכניסה למסך מפוצל על ידי החלקה כלפי מעלה מלחצן הסקירה"</string>
     <string name="experimental" msgid="6198182315536726162">"ניסיוניות"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"‏האם להפעיל את ה-Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"‏כדי לחבר את המקלדת לטאבלט, תחילה עליך להפעיל את ה-Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 7df2f1e..567b034 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ステータスバーに時計の秒を表示します。電池使用量に影響する可能性があります。"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"クイック設定を並べ替え"</string>
     <string name="show_brightness" msgid="6613930842805942519">"クイック設定に明るさ調整バーを表示する"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"上にスワイプして分割画面に切り替える操作を有効にする"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"[概要] ボタンから上にスワイプして分割画面に切り替える操作を有効にします"</string>
     <string name="experimental" msgid="6198182315536726162">"試験運用版"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"BluetoothをONにしますか?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"タブレットでキーボードに接続するには、最初にBluetoothをONにする必要があります。"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 9632a87..fa9af1c 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"საათის წამების ჩვენება სტატუსის ზოლში. შეიძლება გავლენა იქონიოს ბატარეაზე."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"სწრაფი პარამეტრების გადაწყობა"</string>
     <string name="show_brightness" msgid="6613930842805942519">"სიკაშკაშის ჩვენება სწრაფ პარამეტრებში"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"ზემოთ გადაფურცვლისას ეკრანის გაყოფის ჟესტის ჩართვა"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"მიმოხილვის ღილაკიდან ზემოთ გადაფურცვლისას ეკრანის გაყოფის რეჟიმზე გადასვლის ჟესტის ჩართვა"</string>
     <string name="experimental" msgid="6198182315536726162">"ექსპერიმენტული"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"გსურთ Bluetooth-ის ჩართვა?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"კლავიატურის ტაბლეტთან დასაკავშირებლად, ჯერ უნდა ჩართოთ Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index da05ec3..b769e18 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Күйін көрсету жолағында сағат секундтарын көрсету. Батареяның қызмет көрсету мерзіміне әсер етуі мүмкін."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Жылдам параметрлерді қайта реттеу"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Жылдам параметрлерде жарықтықты көрсету"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Бөлінген экранда жоғары қарай сырғыту қимылын қосу"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"\"Шолу\" түймесінен жоғары қарай жанау арқылы бөлінген экранға кіру қимылын қосу"</string>
     <string name="experimental" msgid="6198182315536726162">"Эксперименттік"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth функциясын қосу керек пе?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Пернетақтаны планшетке қосу үшін алдымен Bluetooth функциясын қосу керек."</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index d381da7..ba515bf 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"បង្ហាញវិនាទីនៅលើរបារស្ថានភាពអាចនឹងប៉ះពាល់ដល់ថាមពលថ្ម។"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"រៀបចំការកំណត់រហ័សឡើងវិញ"</string>
     <string name="show_brightness" msgid="6613930842805942519">"បង្ហាញកម្រិតពន្លឺនៅក្នុងការកំណត់រហ័ស"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"បើកដំណើរការកាយវិការអូសទៅលើដើម្បីបំបែកអេក្រង់"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"បើកដំណើរការកាយវិការដើម្បីបំបែកអេក្រង់ដោយអូសទៅលើចាប់ពីប៊ូតុងទិដ្ឋភាព"</string>
     <string name="experimental" msgid="6198182315536726162">"ពិសោធន៍"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"បើកប៊្លូធូសឬ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ដើម្បីភ្ជាប់ក្តារចុចរបស់អ្នកជាមួយនឹងថេប្លេតរបស់អ្នក អ្នកត្រូវតែបើកប៊្លូធូសជាមុនសិន។"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 9b13d80..ecc814b 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಗಡಿಯಾರ ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು. ಇದಕ್ಕೆ ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯು ಪರಿಣಾಮಬೀರಬಹುದು."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌‌ಗಳನ್ನು ಮರುಹೊಂದಿಸಿ"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌‌ಗಳಲ್ಲಿ ಪ್ರಖರತೆಯನ್ನು ತೋರಿಸಿ"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"ಸ್ಪ್ಲಿಟ್-ಸ್ಕ್ರೀನ್ ಸ್ವೈಪ್-ಅಪ್ ಗೆಶ್ಚರ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ಸಮಗ್ರ ನೋಟದ ಬಟನ್‌ನಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಸ್ಪ್ಲಿಟ್‌-ಸ್ಕ್ರೀನ್ ನಮೂದಿಸಲು ಗೆಸ್ಚರ್‌ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="experimental" msgid="6198182315536726162">"ಪ್ರಾಯೋಗಿಕ"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡುವುದೇ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ ಅನ್ನು ಟ್ಯಾಬ್ಲೆಟ್‌ಗೆ ಸಂಪರ್ಕಿಸಲು, ನೀವು ಮೊದಲು ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ."</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index c65af92..9f868e6 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"상태 표시줄에 시계 초 단위를 표시합니다. 배터리 수명에 영향을 줄 수도 있습니다."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"빠른 설정 재정렬"</string>
     <string name="show_brightness" msgid="6613930842805942519">"빠른 설정에서 밝기 표시"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"화면 분할 위로 스와이프 동작 사용"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"최근 사용 버튼에서 위로 스와이프하기 동작으로 창 분할 모드를 사용 설정합니다."</string>
     <string name="experimental" msgid="6198182315536726162">"베타"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"블루투스를 켜시겠습니까?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"키보드를 태블릿에 연결하려면 먼저 블루투스를 켜야 합니다."</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index aaac2ebf..aee615f 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Абал тилкесинен сааттын секунддары көрсөтүлсүн. Батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Ыкчам жөндөөлөрдү кайра коюу"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Ыкчам жөндөөлөрдөн жарык деңгээлин көрсөтүү"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Өйдө серпип экранды бөлүү жаңсоосун иштетүү"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Сереп баскычынан өйдө серпип, экранды бөлүү режимин киргизүү үчүн жаңсоону иштетиңиз"</string>
     <string name="experimental" msgid="6198182315536726162">"Сынамык"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth күйгүзүлсүнбү?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Баскычтобуңузду планшетиңизге туташтыруу үчүн, адегенде Bluetooth\'ту күйгүзүшүңүз керек."</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 8b90611..49aad76 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ສະ​ແດງວິ​ນາ​ທີ​ໂມງ​ຢູ່​ໃນ​ແຖບ​ສະ​ຖາ​ນະ. ອາດ​ຈະ​ມີ​ຜົນ​ກະ​ທົບ​ຕໍ່​ອາ​ຍຸ​ແບັດ​ເຕີ​ຣີ."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ຈັດ​ວາງ​ການ​ຕັ້ງ​ຄ່າ​ດ່ວນ​ຄືນ​ໃໝ່"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ສະ​ແດງ​ຄວາມ​ແຈ້ງ​ຢູ່​ໃນ​ການ​ຕັ້ງ​ຄ່າ​ດ່ວນ"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"ເປີດໃຊ້ທ່າທາງການປັດຂຶ້ນເພື່ອເຂົ້າສູ່ໜ້າຈໍແບບແຍກກັນ"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ເປີດໃຊ້ທ່າທາງເພື່ອເຂົ້າສູ່ໜ້າຈໍແບບແຍກກັນ ໂດຍການປັດຂຶ້ນຈາກປຸ່ມພາບຮວມ"</string>
     <string name="experimental" msgid="6198182315536726162">"ຍັງຢູ່ໃນການທົດລອງ"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ເປີດ​ໃຊ້ Bluetooth ບໍ່?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ເພື່ອ​ເຊື່ອມ​ຕໍ່​ແປ້ນ​ພິມ​ຂອງ​ທ່ານ​ກັບ​ແທັບ​ເລັດ​ຂອງ​ທ່ານ, ກ່ອນ​ອື່ນ​ໝົດ​ທ່ານ​ຕ້ອງ​ເປີດ Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index f933608..4043ef6 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -495,8 +495,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Rodyti laikrodžio sekundes būsenos juostoje. Tai gali paveikti akumuliatoriaus naudojimo laiką."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Pertvarkyti sparčiuosius nustatymus"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Rodyti skaistį sparčiuosiuose nustatymuose"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Įgalinti ekrano skaidymo perbraukimo aukštyn gestą"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Įgalinti gestą, kuriuo galima įjungti skaidytą ekraną, perbraukiant aukštyn nuo apžvalgos mygtuko"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentinė versija"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Įjungti „Bluetooth“?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Kad galėtumėte prijungti klaviatūrą prie planšetinio kompiuterio, pirmiausia turite įjungti „Bluetooth“."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 2c1fb2e..c477cbe 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Statusa joslā rādīt pulksteņa sekundes. Var ietekmēt akumulatora darbības laiku."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Pārkārtot ātros iestatījumus"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Rādīt spilgtumu ātrajos iestatījumos"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Iespējot vilkšanu augšup, lai sadalītu ekrānu"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Iespējot žestu ekrāna sadalīšanai, velkot augšup no pogas Pārskats"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentāli"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vai ieslēgt Bluetooth savienojumu?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Lai pievienotu tastatūru planšetdatoram, vispirms ir jāieslēdz Bluetooth savienojums."</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index b28938a..ff7a25d 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Прикажи ги секундите на часовникот на статусната лента. Може да влијае на траењето на батеријата."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Преуредете ги Брзи поставки"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Прикажете ја осветленоста во Брзи поставки"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Овозможи го гестот повлекување нагоре за поделен екран"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Овозможете гест за отворање поделен екран со повлекување нагоре од копчето Краток преглед"</string>
     <string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Да се вклучи Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"За да ја поврзете тастатурата со таблетот, најпрво треба да вклучите Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index c5a440d..fa4f326 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"സ്റ്റാറ്റസ് ബാറിൽ ക്ലോക്ക് സെക്കൻഡ് കാണിക്കുന്നത് ബാറ്ററിയുടെ ലൈഫിനെ ബാധിക്കാം."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ദ്രുത ക്രമീകരണം പുനഃസജ്ജീകരിക്കുക"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ദ്രുത ക്രമീകരണത്തിൽ തെളിച്ചം കാണിക്കുക"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"സ്പ്ലിറ്റ്-സ്ക്രീൻ സ്വൈപ്പ്-അപ്പ് ജെസ്റ്റർ പ്രവർത്തനക്ഷമമാക്കുക"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ചുരുക്കവിവരണ ബട്ടണിൽ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പുചെയ്തുകൊണ്ട് സ്പ്ലിറ്റ്-സ്ക്രീനിലേക്ക് പ്രവേശിക്കാൻ ജെസ്‌റ്റർ പ്രവർത്തനക്ഷമമാക്കുക"</string>
     <string name="experimental" msgid="6198182315536726162">"പരീക്ഷണാത്മകം!"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ഓണാക്കണോ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"നിങ്ങളുടെ ടാബ്‌ലെറ്റുമായി കീബോർഡ് കണക്റ്റുചെയ്യുന്നതിന്, ആദ്യം Bluetooth ഓണാക്കേണ്ടതുണ്ട്."</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 766af7c..a42b7f9 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Статус талбарт цагийн секундыг харуулах. Энэ нь тэжээлийн цэнэгт нөлөөлж болно."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Түргэн тохиргоог дахин засварлах"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Түргэн тохиргоонд гэрэлтүүлэг харах"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Дэлгэц хуваах дээш шудрах дохиог идэвхжүүлэх"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Тойм товчлуурыг дээш шударч, хуваагдсан дэлгэцэд зангаагаар орох тохиргоог идэвхжүүлэх"</string>
     <string name="experimental" msgid="6198182315536726162">"Туршилтын"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth-г асаах уу?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Компьютерийн гараа таблетад холбохын тулд эхлээд Bluetooth-г асаана уу."</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 82a07ba..d7f4d34 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"स्टेटस बारमध्‍ये घड्‍याळ सेकंद दर्शवा. कदाचित बॅटरी आयुष्‍य प्रभावित होऊ शकते."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिंग्जची पुनर्रचना करा"</string>
     <string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिंग्जमध्‍ये चमक दर्शवा"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"विभाजित-स्क्रीन स्वाइप-अप जेश्चर सक्षम करा"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"विहंगावलोकन बटणावरून वर स्वाइप करून विभाजित-स्क्रीन प्रविष्ट करण्यासाठी जेश्चर सक्षम करा"</string>
     <string name="experimental" msgid="6198182315536726162">"प्रायोगिक"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटुथ सुरू करायचे?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"आपला कीबोर्ड आपल्या टॅब्लेटसह कनेक्ट करण्यासाठी, आपल्याला प्रथम ब्लूटुथ चालू करणे आवश्यक आहे."</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index c653f25..4506e6b 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Tunjukkan saat jam dalam bar status. Mungkin menjejaskan hayat bateri."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Susun Semula Tetapan Pantas"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Tunjukkan kecerahan dalam Tetapan Pantas"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Dayakan gerak isyarat leret ke atas utk masuk skrin terpisah"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Dayakan gerak isyarat untuk memasuki skrin terpisah dengan meleret ke atas daripada butang Ikhtisar"</string>
     <string name="experimental" msgid="6198182315536726162">"Percubaan"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Hidupkan Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Untuk menyambungkan papan kekunci anda dengan tablet, anda perlu menghidupkan Bluetooth terlebih dahulu."</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 47f5a86..5af9d47 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"အခြေအနေပြနေရာမှာ နာရီ စက္ကန့်များကို ပြပါ။ ဘက်ထရီ သက်တမ်းကို အကျိုးသက်ရောက်နိုင်တယ်။"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"အမြန် ဆက်တင်များကို ပြန်စီစဉ်ရန်"</string>
     <string name="show_brightness" msgid="6613930842805942519">"အမြန် ဆက်တင်များထဲက တောက်ပမှုကို ပြရန်"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"မျက်နှာပြင်ခွဲကြည့်ရန် အပေါ်သို့ပွတ်ဆွဲခြင်း အမူအရာကိုဖွင့်ပါ"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ခြုံကြည့်သည့်ခလုတ်မှ အပေါ်သို့ပွတ်ဆွဲခြင်းဖြင့် မျက်နှာပြင်ခွဲကြည့်ရန် လက်ဟန်ကိုဖွင့်ပါ"</string>
     <string name="experimental" msgid="6198182315536726162">"စမ်းသပ်ရေး"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ဘလူးတုသ် ဖွင့်ရမလား။"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ကီးဘုတ်ကို တပ်ဘလက်နှင့် ချိတ်ဆက်ရန်၊ ပမထဦးစွာ ဘလူးတုသ်ကို ဖွင့်ပါ။"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index de88e15..e170244 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statusfeltet på klokken. Det kan påvirke batteritiden."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Omorganiser hurtiginnstillingene"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i hurtiginnstillingene"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Slå på delt skjerm ved å sveipe opp"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Slå på bevegelsen for å åpne delt skjerm ved å sveipe opp fra Oversikt-knappen"</string>
     <string name="experimental" msgid="6198182315536726162">"På forsøksstadiet"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå på Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"For å koble tastaturet til nettbrettet ditt må du først slå på Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 198555b..da9db1f 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"वस्तुस्थिति पट्टीको घडीमा सेकेन्ड देखाउनुहोस्। ब्याट्री आयु प्रभावित हुन सक्छ।"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिङहरू पुनः व्यवस्थित गर्नुहोस्"</string>
     <string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिङहरूमा उज्यालो देखाउनुहोस्"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"विभाजित-स्क्रिन स्वाइप-अप इशारा सक्षम गर्नुहोस्"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"परिदृश्य बटनदेखि माथि स्वाइप गरी विभाजित-स्क्रिन प्रविष्ट गर्न इसारालाई सक्रिय गर्नुहोस्"</string>
     <string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लुटुथ सक्रिय पार्ने हो?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"आफ्नो ट्याब्लेटसँग किबोर्ड जोड्न, पहिले तपाईँले ब्लुटुथ सक्रिय गर्नुपर्छ।"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 8ba27af..f3b082a 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Klokseconden op de statusbalk weergeven. Kan van invloed zijn op de accuduur."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Snelle instellingen opnieuw indelen"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Helderheid weergeven in Snelle instellingen"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Omhoog vegen voor gesplitst scherm inschakelen"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Gebaar inschakelen om gesplitst scherm te openen door vanaf de knop Overzicht omhoog te vegen"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimenteel"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth inschakelen?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Als je je toetsenbord wilt verbinden met je tablet, moet je eerst Bluetooth inschakelen."</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index dbf9f86..3811999 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ਸਥਿਤੀ ਬਾਰ ਵਿੱਚ ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ। ਬੈਟਰੀ ਸਮਰੱਥਾ ਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ।"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਨੂੰ ਦੁਬਾਰਾ ਕ੍ਰਮ ਦਿਓ"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਮਕ ਦਿਖਾਓ"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਸਵਾਈਪ-ਅੱਪ ਸੰਕੇਤ ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"ਰੂਪ-ਰੇਖਾ ਬਟਨ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰਨ ਦੁਆਰਾ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਵਿੱਚ ਦਾਖਲ ਹੋਣ ਲਈ ਸੰਕੇਤ ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
     <string name="experimental" msgid="6198182315536726162">"ਪ੍ਰਯੋਗਾਤਮਿਕ"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth ਚਾਲੂ ਕਰੋ?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ਆਪਣੇ ਟੈਬਲੇਟ ਨਾਲ ਆਪਣਾ ਕੀ-ਬੋਰਡ ਕਨੈਕਟ ਕਰਨ ਲਈ, ਤੁਹਾਨੂੰ ਪਹਿਲਾਂ Bluetooth ਚਾਲੂ ਕਰਨ ਦੀ ਜ਼ਰੂਰਤ ਹੈ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 294381e..5a9da97 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -495,8 +495,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Pokaż sekundy na zegarku na pasku stanu. Może mieć wpływ na czas pracy baterii."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Uporządkuj Szybkie ustawienia"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Pokaż jasność w Szybkich ustawieniach"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Włącz dzielenie ekranu gestem przesunięcia w górę"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Włącz dzielenie ekranu po wykonaniu gestu przesunięcia palcem w górę od przycisku Przegląd"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperymentalne"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Włączyć Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Aby połączyć klawiaturę z tabletem, musisz najpierw włączyć Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 89aa5d3..ab797a5 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ativar gesto para dividir a tela ao deslizar para cima"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Ativa o gesto para entrar no modo de tela dividida deslizando a partir do botão \"Visão geral\""</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Ativar o Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index e06df93..46a744a 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de estado. Pode afetar a autonomia da bateria."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar as Definições rápidas"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar luminosidade nas Definições rápidas"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ativar gesto de deslize rápido para cima do ecrã dividido"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Ativar o gesto para aceder ao ecrã dividido ao deslizar rapidamente para cima a partir do botão Vista geral"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Pretende ativar o Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para ligar o teclado ao tablet, tem de ativar primeiro o Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 89aa5d3..ab797a5 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ativar gesto para dividir a tela ao deslizar para cima"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Ativa o gesto para entrar no modo de tela dividida deslizando a partir do botão \"Visão geral\""</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Ativar o Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 11ef6f1..8b4c657 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -495,8 +495,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Afișează secundele pe ceas în bara de stare. Poate afecta autonomia bateriei."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Rearanjați Setările rapide"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Afișați luminozitatea în Setările rapide"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Activați gestul de accesare a ecranului împărțit prin glisare în sus"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Activați gestul de accesare a ecranului împărțit prin glisarea în sus de la butonul Recente"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentale"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Activați Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Pentru a conecta tastatura la tabletă, mai întâi trebuie să activați Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index c4205fb..870e67f 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -497,8 +497,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Показывать в строке состояния время с точностью до секунды (заряд батареи может расходоваться быстрее)."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Изменить порядок Быстрых настроек"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Добавить яркость в Быстрые настройки"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Разделять экран пролистыванием вверх"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Включить разделение экрана пролистыванием вверх с кнопки \"Обзор\""</string>
     <string name="experimental" msgid="6198182315536726162">"Экспериментальная функция"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Подключение по Bluetooth"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Чтобы подключить клавиатуру к планшету, включите Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 3b49cc1..d5ff0a6 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"තත්ත්ව තීරුවෙහි ඔරලෝසු තත්පර පෙන්වන්න. බැටරි ආයු කාලයට බලපෑමට හැකිය."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ඉක්මන් සැකසීම් යළි පිළිවෙළට සකසන්න"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ඉක්මන් සැකසීම්වල දීප්තිය පෙන්වන්න"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"බෙදුම්-තිරය ඉහළට-ස්වයිප් කිරීමේ අභිනය සබල කරන්න"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"දළ විශ්ලේෂණ බොත්තම හරහා ඉහළට ස්වයිප් කිරීමෙන් බෙදුම් තිරයට ඇතුළු වීමට ඉඟිය සබල කිරීම"</string>
     <string name="experimental" msgid="6198182315536726162">"පරීක්ෂණාත්මක"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"බ්ලූටූත් ක්‍රියාත්මක කරන්නද?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"ඔබේ යතුරු පුවරුව ඔබේ ටැබ්ලට් පරිගණකයට සම්බන්ධ කිරීමට, ඔබ පළමුව බ්ලූටූත් ක්‍රියාත්මක කළ යුතුය."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 099e9c1..0bafcfd 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -497,8 +497,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Zobrazí sekundy v stavovom riadku. Môže to ovplyvňovať výdrž batérie."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Zmeniť usporiadanie Rýchlych nastavení"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Zobraziť jas v Rýchlych nastaveniach"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktivovať rozdelenú obrazovku prejdením prstom"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Umožňuje aktivovať rozdelenú obrazovku prejdením prstom nahor od tlačidla Prehľad"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentálne"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Zapnúť Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Ak chcete klávesnicu pripojiť k tabletu, najprv musíte zapnúť Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 49fc355..04dfdab 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -497,8 +497,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Prikaže sekunde pri uri v vrstici stanja. To lahko vpliva na čas delovanja pri akumulatorskem napajanju."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Preuredi hitre nastavitve"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Prikaz svetlosti v hitrih nastavitvah"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Omogočanje poteze za razdeljen zaslon z vlečenjem navzgor"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Omogočanje poteze za vklop razdeljenega zaslona, tako da uporabnik od gumba za pregled povleče s prstom navzgor"</string>
     <string name="experimental" msgid="6198182315536726162">"Poskusno"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite vklopiti Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Če želite povezati tipkovnico in tablični računalnik, vklopite Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 92b8e35..b12a946 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Trego sekondat e orës në shiritin e statusit. Mund të ndikojë te jeta e baterisë."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Risistemo Cilësimet e shpejta"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Shfaq ndriçimin te Cilësimet e shpejta"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktivizo gjestin e rrëshqitjes lart për ekranin e ndarë"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktivizo gjestin për të hyrë tek ekrani i ndarë duke rrëshqitur lart nga butoni \"Përmbledhja\""</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentale"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Të aktivizohet \"bluetooth-i\"?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Për të lidhur tastierën me tabletin, në fillim duhet të aktivizosh \"bluetooth-in\"."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 9c4fefb9..b08e3b0 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Секунде на сату се приказују на статусној траци. То може да утиче на трајање батерије."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Преуреди Брза подешавања"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Прикажи осветљеност у Брзим подешавањима"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Омогући покрет за превлачење нагоре за подељени екран"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Омогућава покрет за прелазак на подељени екран превлачењем нагоре од дугмета Преглед"</string>
     <string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Желите ли да укључите Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Да бисте повезали тастатуру са таблетом, прво морате да укључите Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 4b15537..c923d30 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Visa klocksekunder i statusfältet. Detta kan påverka batteritiden."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Ordna snabbinställningarna"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Visa ljusstyrka i snabbinställningarna"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Aktivera delad skärm när du sveper uppåt"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Aktivera en rörelse som delar skärmen när du sveper uppåt från knappen Översikt"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentella"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vill du aktivera Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Om du vill ansluta tangentbordet till surfplattan måste du först aktivera Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 101bfa4..96ab952 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Onyesha sekunde za saa katika sehemu ya arifa. Inaweza kuathiri muda wa matumizi ya betri."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Panga Upya Mipangilio ya Haraka"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Onyesha unga\'avu katika Mipangilio ya Haraka"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Ruhusu kugawanya skrini kwa ishara ya kutelezesha kidole juu"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Washa kipengele cha ishara ili utumie skrini iliyogawanywa kwa kutelezesha kidole juu kutoka kitufe cha Muhtasari"</string>
     <string name="experimental" msgid="6198182315536726162">"Ya majaribio"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Je, ungependa kuwasha Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Ili uunganishe Kibodi yako kwenye kompyuta yako kibao, lazima kwanza uwashe Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index d7ef941..1c4e8b1 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"நிலைப் பட்டியில் கடிகார வினாடிகளைக் காட்டும். பேட்டரியின் ஆயுளைக் குறைக்கலாம்."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"விரைவு அமைப்புகளை மறுவரிசைப்படுத்து"</string>
     <string name="show_brightness" msgid="6613930842805942519">"விரைவு அமைப்புகளில் ஒளிர்வுப் பட்டியைக் காட்டு"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"மேலே ஸ்வைப் செய்வதன் மூலம் திரையைப் பிரிக்கும் சைகையை இயக்கு"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"மேலோட்டப் பார்வை பொத்தானிலிருந்து மேலே ஸ்வைப் செய்வதன் மூலம், திரைப் பிரிப்பைச் செயலாக்குவதற்கான சைகையை இயக்கும்"</string>
     <string name="experimental" msgid="6198182315536726162">"சோதனை முயற்சி"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"புளூடூத்தை இயக்கவா?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"உங்கள் டேப்லெட்டுடன் விசைப்பலகையை இணைக்க, முதலில் புளூடூத்தை இயக்க வேண்டும்."</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 29c8781..ac586cc 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"స్థితి పట్టీలో గడియారం సెకన్లు చూపుతుంది. బ్యాటరీ శక్తి ప్రభావితం చేయవచ్చు."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"శీఘ్ర సెట్టింగ్‌ల ఏర్పాటు క్రమం మార్చు"</string>
     <string name="show_brightness" msgid="6613930842805942519">"శీఘ్ర సెట్టింగ్‌ల్లో ప్రకాశం చూపు"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"పైకి స్వైప్ చేయడం ద్వారా స్క్రీన్ విభజన సంజ్ఞను ప్రారంభించు"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"స్థూలదృష్టి బటన్ నుండి పైకి స్వైప్ చేయడం ద్వారా స్క్రీన్ విభజనలోకి ప్రవేశించడానికి సంజ్ఞను ప్రారంభిస్తుంది"</string>
     <string name="experimental" msgid="6198182315536726162">"ప్రయోగాత్మకం"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"బ్లూటూత్ ఆన్ చేయాలా?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"మీ కీబోర్డ్‌ను మీ టాబ్లెట్‌తో కనెక్ట్ చేయడానికి, మీరు ముందుగా బ్లూటూత్ ఆన్ చేయాలి."</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 808a2a1..c04f238 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"แสดงวินาทีของนาฬิกาในแถบสถานะ อาจส่งผลต่ออายุแบตเตอรี"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"จัดเรียงการตั้งค่าด่วนใหม่"</string>
     <string name="show_brightness" msgid="6613930842805942519">"แสดงความสว่างในการตั้งค่าด่วน"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"เปิดใช้ท่าทางสัมผัสการเลื่อนขึ้นเพื่อแยกหน้าจอ"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"เปิดใช้ท่าทางสัมผัสเพื่อเข้าสู่โหมดแยกหน้าจอโดยเลื่อนขึ้นจากปุ่มภาพรวม"</string>
     <string name="experimental" msgid="6198182315536726162">"ทดสอบ"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"เปิดบลูทูธไหม"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"หากต้องการเชื่อมต่อแป้นพิมพ์กับแท็บเล็ต คุณต้องเปิดบลูทูธก่อน"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 1eb5295..b8c83fa 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Ipakita ang mga segundo ng orasan sa status bar. Maaaring makaapekto sa tagal ng baterya."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Ayusing Muli ang Mga Mabilisang Setting"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Ipakita ang liwanag sa Mga Mabilisang Setting"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"I-enable ang pag-swipe pataas na galaw para sa split-screen"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"I-enable ang gesture upang makapasok sa split-screen sa pamamagitan ng pagsa-swipe pataas mula sa button ng Pangkalahatang-ideya"</string>
     <string name="experimental" msgid="6198182315536726162">"Pang-eksperimento"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"I-on ang Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Upang ikonekta ang iyong keyboard sa iyong tablet, kailangan mo munang i-on ang Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index f29d9b5..e0e7d31 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Durum çubuğunda saatin saniyelerini gösterir. Pil ömrünü etkileyebilir."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Hızlı Ayarlar\'ı Yeniden Düzenle"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Hızlı Ayarlar\'da parlaklığı göster"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Hızlıca yukarı kaydırma hareketiyle ekran bölm. etkinleştir"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Genel bakış düğmesinden yukarı hızlıca kaydırarak bölünmüş ekrana geçme hareketini etkinleştir"</string>
     <string name="experimental" msgid="6198182315536726162">"Deneysel"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth açılsın mı?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Klavyenizi tabletinize bağlamak için önce Bluetooth\'u açmanız gerekir."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index a930589..5d61e66 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -497,8 +497,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Показувати секунди на годиннику в рядку стану. Акумулятор може розряджатися швидше."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Упорядкувати швидкі налаштування"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Показувати панель яскравості у швидких налаштуваннях"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Увімкнути розділення екрана рухом пальця вгору"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Увімкнути жест розділення екрана рухом пальця вгору від кнопки \"Огляд\""</string>
     <string name="experimental" msgid="6198182315536726162">"Експериментальні налаштування"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Увімкнути Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Щоб під’єднати клавіатуру до планшета, спершу потрібно ввімкнути Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 16c1792..01e690b 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"گھڑی کے سیکنڈز اسٹیٹس بار میں دکھائیں۔ اس کا بیٹری کی زندگی پر اثر پڑ سکتا ہے۔"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"فوری ترتیبات کو دوبارہ ترتیب دیں"</string>
     <string name="show_brightness" msgid="6613930842805942519">"فوری ترتیبات میں چمکیلا پن دکھائیں"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"سپلٹ اسکرین کیلئے سوائپ اپ اشارہ فعال کریں"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"مجموعی جائزہ بٹن سے سوائپ اپ کرکے سپلٹ اسکرین میں داخل ہونے کیلئے اشارہ فعال کریں"</string>
     <string name="experimental" msgid="6198182315536726162">"تجرباتی"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"بلوٹوتھ آن کریں؟"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"اپنے کی بورڈ کو اپنے ٹیبلٹ کے ساتھ منسلک کرنے کیلئے پہلے آپ کو اپنا بلو ٹوتھ آن کرنا ہو گا۔"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index eb6ffb3..ed3edc8 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Holat panelida soat soniyalari ko‘rsatilsin. Bu batareya resursiga ta’sir qilishi mumkin."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Tezkor sozlamalarni qayta tartiblash"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Tezkor sozlamalarda yorqinlikni ko‘rsatish"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Tepaga surish orqali ekranni ikkiga bo‘lish"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Umumiy ma’lumot tugmasini tepaga surish orqali ekranni bo‘lish ishorasini yoqish"</string>
     <string name="experimental" msgid="6198182315536726162">"Tajribaviy"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth yoqilsinmi?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Klaviaturani planshetingizga ulash uchun Bluetooth xizmatini yoqishingiz kerak."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index a15ba26..de2206d 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Hiển thị giây đồng hồ trong thanh trạng thái. Có thể ảnh hưởng đến thời lượng pin."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Sắp xếp lại Cài đặt nhanh"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Hiển thị độ sáng trong Cài đặt nhanh"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Bật cử chỉ vuốt lên ở chế độ chia đôi màn hình"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Cho phép cử chỉ truy cập chế độ chia đôi màn hình bằng cách vuốt lên từ nút Tổng quan"</string>
     <string name="experimental" msgid="6198182315536726162">"Thử nghiệm"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Bật Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Để kết nối bàn phím với máy tính bảng, trước tiên, bạn phải bật Bluetooth."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index e4572fe..b98aeaa 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"在状态栏中显示时钟的秒数。这可能会影响电池的续航时间。"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"重新排列快捷设置"</string>
     <string name="show_brightness" msgid="6613930842805942519">"在快捷设置中显示亮度栏"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"启用分屏上滑手势"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"启用通过从“概览”按钮向上滑动的手势进入分屏模式"</string>
     <string name="experimental" msgid="6198182315536726162">"实验性功能"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"要开启蓝牙吗?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"要将您的键盘连接到平板电脑,您必须先开启蓝牙。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 486c23e..1c2445a 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -493,8 +493,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數,但可能會影響電池壽命。"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
     <string name="show_brightness" msgid="6613930842805942519">"在快速設定顯示亮度"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"啟用分割畫面向上快速滑動手勢"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"從 [概覽] 按鈕向上快速滑動,即可使用手勢功能進入分割畫面模式"</string>
     <string name="experimental" msgid="6198182315536726162">"實驗版"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"要開啟藍牙嗎?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"如要將鍵盤連接至平板電腦,請先開啟藍牙。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index e0162bc..e2884a2 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數。這可能會影響電池續航力。"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
     <string name="show_brightness" msgid="6613930842805942519">"在快速設定中顯示亮度"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"啟用分割畫面向上滑動手勢"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"啟用透過從 [總覽] 按鈕向上滑動的手勢進入分割畫面"</string>
     <string name="experimental" msgid="6198182315536726162">"實驗性"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"要開啟藍牙功能嗎?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"如要將鍵盤連線到平板電腦,您必須先開啟藍牙。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index a2c31d6..ae08198 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -491,8 +491,6 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Bonisa amasekhondi wewashi kubha yesimo. Ingathinta impilo yebhethri."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Hlela kabusha izilungiselelo ezisheshayo"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Bonisa ukukhanya kuzilungiselelo ezisheshayo"</string>
-    <string name="overview_nav_bar_gesture" msgid="8579814204727917764">"Nika amandla ukuthinta kokuswayiphela phezulu ukuhlukanisa isikrini"</string>
-    <string name="overview_nav_bar_gesture_desc" msgid="6329167382305102615">"Nika amandla ukuthinta ukuze ungene ekuhlukaniseni isikrini ngokuswayiphela phezulu kusukela kunkinobho yokubuka konke"</string>
     <string name="experimental" msgid="6198182315536726162">"Okokulinga"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vula i-Bluetooth?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Ukuze uxhume ikhibhodi yakho nethebhulethi yakho, kufanele uqale ngokuvula i-Bluetooth."</string>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 7ec6a03..e05e507 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -90,10 +90,10 @@
         }
 
         @Override // Binder interface
-        public void setOccluded(boolean isOccluded) {
+        public void setOccluded(boolean isOccluded, boolean animate) {
             Trace.beginSection("KeyguardService.mBinder#setOccluded");
             checkPermission();
-            mKeyguardViewMediator.setOccluded(isOccluded);
+            mKeyguardViewMediator.setOccluded(isOccluded, animate);
             Trace.endSection();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 2ab2a8c..aa6e88c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1126,11 +1126,11 @@
     /**
      * Notify us when the keyguard is occluded by another window
      */
-    public void setOccluded(boolean isOccluded) {
+    public void setOccluded(boolean isOccluded, boolean animate) {
         Trace.beginSection("KeyguardViewMediator#setOccluded");
         if (DEBUG) Log.d(TAG, "setOccluded " + isOccluded);
         mHandler.removeMessages(SET_OCCLUDED);
-        Message msg = mHandler.obtainMessage(SET_OCCLUDED, (isOccluded ? 1 : 0), 0);
+        Message msg = mHandler.obtainMessage(SET_OCCLUDED, isOccluded ? 1 : 0, animate ? 1 : 0);
         mHandler.sendMessage(msg);
         Trace.endSection();
     }
@@ -1138,7 +1138,7 @@
     /**
      * Handles SET_OCCLUDED message sent by setOccluded()
      */
-    private void handleSetOccluded(boolean isOccluded) {
+    private void handleSetOccluded(boolean isOccluded, boolean animate) {
         Trace.beginSection("KeyguardViewMediator#handleSetOccluded");
         synchronized (KeyguardViewMediator.this) {
             if (mHiding && isOccluded) {
@@ -1149,7 +1149,7 @@
 
             if (mOccluded != isOccluded) {
                 mOccluded = isOccluded;
-                mStatusBarKeyguardViewManager.setOccluded(isOccluded);
+                mStatusBarKeyguardViewManager.setOccluded(isOccluded, animate);
                 updateActivityLockScreenState();
                 adjustStatusBarLocked();
             }
@@ -1489,7 +1489,7 @@
                     break;
                 case SET_OCCLUDED:
                     Trace.beginSection("KeyguardViewMediator#handleMessage SET_OCCLUDED");
-                    handleSetOccluded(msg.arg1 != 0);
+                    handleSetOccluded(msg.arg1 != 0, msg.arg2 != 0);
                     Trace.endSection();
                     break;
                 case KEYGUARD_TIMEOUT:
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java
new file mode 100644
index 0000000..ffe66f4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/PackageManagerAdapter.java
@@ -0,0 +1,59 @@
+/*
+ * 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.qs.external;
+
+import android.annotation.UserIdInt;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.os.RemoteException;
+
+// Adapter that wraps calls to PackageManager or IPackageManager for {@link TileLifecycleManager}.
+// TODO: This is very much an intermediate step to allow for PackageManager mocking and should be
+// abstracted into something more useful for other tests in systemui.
+public class PackageManagerAdapter {
+    private static final String TAG = "PackageManagerAdapter";
+
+    private PackageManager mPackageManager;
+    private IPackageManager mIPackageManager;
+
+    // Uses the PackageManager for the provided context.
+    // When necessary, uses the IPackagemanger in AppGlobals.
+    public PackageManagerAdapter(Context context) {
+        mPackageManager = context.getPackageManager();
+        mIPackageManager = AppGlobals.getPackageManager();
+    }
+
+    public ServiceInfo getServiceInfo(ComponentName className, int flags, int userId)
+            throws RemoteException {
+        return mIPackageManager.getServiceInfo(className, flags, userId);
+    }
+
+    public ServiceInfo getServiceInfo(ComponentName component, int flags)
+            throws PackageManager.NameNotFoundException {
+        return mPackageManager.getServiceInfo(component, flags);
+    }
+
+    public PackageInfo getPackageInfoAsUser(String packageName, int flags, @UserIdInt int userId)
+            throws PackageManager.NameNotFoundException {
+        return mPackageManager.getPackageInfoAsUser(packageName, flags, userId);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 28da69c..c432096 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -21,10 +21,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ServiceInfo;
+import android.content.ServiceConnection;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Handler;
@@ -38,6 +37,7 @@
 import android.support.annotation.VisibleForTesting;
 import android.util.ArraySet;
 import android.util.Log;
+import com.android.systemui.qs.external.PackageManagerAdapter;
 
 import libcore.util.Objects;
 
@@ -73,6 +73,7 @@
     private final Intent mIntent;
     private final UserHandle mUser;
     private final IBinder mToken = new Binder();
+    private final PackageManagerAdapter mPackageManagerAdapter;
 
     private Set<Integer> mQueuedMessages = new ArraySet<>();
     private QSTileServiceWrapper mWrapper;
@@ -88,14 +89,21 @@
     // Return value from bindServiceAsUser, determines whether safe to call unbind.
     private boolean mIsBound;
 
-    public TileLifecycleManager(Handler handler, Context context, IQSService service,
-            Tile tile, Intent intent, UserHandle user) {
+    public TileLifecycleManager(Handler handler, Context context, IQSService service, Tile tile,
+            Intent intent, UserHandle user) {
+        this(handler, context, service, tile, intent, user, new PackageManagerAdapter(context));
+    }
+
+    @VisibleForTesting
+    TileLifecycleManager(Handler handler, Context context, IQSService service, Tile tile,
+            Intent intent, UserHandle user, PackageManagerAdapter packageManagerAdapter) {
         mContext = context;
         mHandler = handler;
         mIntent = intent;
         mIntent.putExtra(TileService.EXTRA_SERVICE, service.asBinder());
         mIntent.putExtra(TileService.EXTRA_TOKEN, mToken);
         mUser = user;
+        mPackageManagerAdapter = packageManagerAdapter;
         if (DEBUG) Log.d(TAG, "Creating " + mIntent + " " + mUser);
     }
 
@@ -111,11 +119,11 @@
 
     public boolean isActiveTile() {
         try {
-            ServiceInfo info = mContext.getPackageManager().getServiceInfo(mIntent.getComponent(),
+            ServiceInfo info = mPackageManagerAdapter.getServiceInfo(mIntent.getComponent(),
                     PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_META_DATA);
             return info.metaData != null
                     && info.metaData.getBoolean(TileService.META_DATA_ACTIVE_TILE, false);
-        } catch (NameNotFoundException e) {
+        } catch (PackageManager.NameNotFoundException e) {
             return false;
         }
     }
@@ -129,6 +137,12 @@
     }
 
     public void setBindService(boolean bind) {
+        if (mBound && mUnbindImmediate) {
+            // If we are already bound and expecting to unbind, this means we should stay bound
+            // because something else wants to hold the connection open.
+            mUnbindImmediate = false;
+            return;
+        }
         mBound = bind;
         if (bind) {
             if (mBindTryCount == MAX_BIND_RETRIES) {
@@ -255,8 +269,7 @@
     }
 
     private boolean checkComponentState() {
-        PackageManager pm = mContext.getPackageManager();
-        if (!isPackageAvailable(pm) || !isComponentAvailable(pm)) {
+        if (!isPackageAvailable() || !isComponentAvailable()) {
             startPackageListening();
             return false;
         }
@@ -305,10 +318,10 @@
         }
     }
 
-    private boolean isComponentAvailable(PackageManager pm) {
+    private boolean isComponentAvailable() {
         String packageName = mIntent.getComponent().getPackageName();
         try {
-            ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(mIntent.getComponent(),
+            ServiceInfo si = mPackageManagerAdapter.getServiceInfo(mIntent.getComponent(),
                     0, mUser.getIdentifier());
             if (DEBUG && si == null) Log.d(TAG, "Can't find component " + mIntent.getComponent());
             return si != null;
@@ -318,10 +331,10 @@
         return false;
     }
 
-    private boolean isPackageAvailable(PackageManager pm) {
+    private boolean isPackageAvailable() {
         String packageName = mIntent.getComponent().getPackageName();
         try {
-            pm.getPackageInfoAsUser(packageName, 0, mUser.getIdentifier());
+            mPackageManagerAdapter.getPackageInfoAsUser(packageName, 0, mUser.getIdentifier());
             return true;
         } catch (PackageManager.NameNotFoundException e) {
             if (DEBUG) Log.d(TAG, "Package not available: " + packageName, e);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 8493cc6..91a0eb0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -95,6 +95,7 @@
         if (!TileLifecycleManager.isTileAdded(context, component)) {
             TileLifecycleManager.setTileAdded(context, component, true);
             mStateManager.onTileAdded();
+            mStateManager.flushMessagesAndUnbind();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index af85101..a6a5742 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -92,6 +92,7 @@
      * Whether an instant expand request is currently pending and we are just waiting for layout.
      */
     private boolean mInstantExpanding;
+    private boolean mAnimateAfterExpanding;
 
     PanelBar mBar;
 
@@ -656,7 +657,7 @@
                 vel = 0;
             }
             mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight());
-            if (expandBecauseOfFalsing) {
+            if (vel == 0) {
                 animator.setDuration(350);
             }
         } else {
@@ -870,6 +871,7 @@
         }
 
         mInstantExpanding = true;
+        mAnimateAfterExpanding = animate;
         mUpdateFlingOnLayout = false;
         abortAnimations();
         cancelPeek();
@@ -894,7 +896,7 @@
                         if (mStatusBar.getStatusBarWindow().getHeight()
                                 != mStatusBar.getStatusBarHeight()) {
                             getViewTreeObserver().removeOnGlobalLayoutListener(this);
-                            if (animate) {
+                            if (mAnimateAfterExpanding) {
                                 notifyExpandingStarted();
                                 fling(0, true /* expand */);
                             } else {
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 893590d..ebd4798 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -279,6 +279,14 @@
      */
     private static final int REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY = 200;
 
+    /**
+     * Never let the alpha become zero for surfaces that draw with SRC - otherwise the RenderNode
+     * won't draw anything and uninitialized memory will show through
+     * if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in
+     * libhwui.
+     */
+    private static final float SRC_MIN_ALPHA = 0.002f;
+
     static {
         boolean onlyCoreApps;
         boolean freeformWindowManagement;
@@ -2213,17 +2221,13 @@
             if (mBackdrop.getVisibility() != View.VISIBLE) {
                 mBackdrop.setVisibility(View.VISIBLE);
                 if (allowEnterAnimation) {
-                    mBackdrop.animate().alpha(1f).withEndAction(new Runnable() {
-                        @Override
-                        public void run() {
-                            mStatusBarWindowManager.setBackdropShowing(true);
-                        }
-                    });
+                    mBackdrop.setAlpha(SRC_MIN_ALPHA);
+                    mBackdrop.animate().alpha(1f);
                 } else {
                     mBackdrop.animate().cancel();
                     mBackdrop.setAlpha(1f);
-                    mStatusBarWindowManager.setBackdropShowing(true);
                 }
+                mStatusBarWindowManager.setBackdropShowing(true);
                 metaDataChanged = true;
                 if (DEBUG_MEDIA) {
                     Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork");
@@ -2286,11 +2290,7 @@
                 } else {
                     mStatusBarWindowManager.setBackdropShowing(false);
                     mBackdrop.animate()
-                            // Never let the alpha become zero - otherwise the RenderNode
-                            // won't draw anything and uninitialized memory will show through
-                            // if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in
-                            // libhwui.
-                            .alpha(0.002f)
+                            .alpha(SRC_MIN_ALPHA)
                             .setInterpolator(Interpolators.ACCELERATE_DECELERATE)
                             .setDuration(300)
                             .setStartDelay(0)
@@ -2305,7 +2305,6 @@
                             });
                     if (mKeyguardFadingAway) {
                         mBackdrop.animate()
-
                                 // Make it disappear faster, as the focus should be on the activity
                                 // behind.
                                 .setDuration(mKeyguardFadingAwayDuration / 2)
@@ -4140,6 +4139,15 @@
     }
 
     /**
+     * Plays the animation when an activity that was occluding Keyguard goes away.
+     */
+    public void animateKeyguardUnoccluding() {
+        mScrimController.animateKeyguardUnoccluding(500);
+        mNotificationPanel.setExpandedFraction(0f);
+        animateExpandNotificationsPanel();
+    }
+
+    /**
      * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that
      * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen
      * because the launched app crashed or something else went wrong.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 40abaa4..e46f8f4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -185,6 +185,14 @@
         }
     }
 
+    public void animateKeyguardUnoccluding(long duration) {
+        mAnimateChange = false;
+        setScrimBehindColor(0f);
+        mAnimateChange = true;
+        scheduleUpdate();
+        mDurationOverride = duration;
+    }
+
     public void animateGoingToFullShade(long delay, long duration) {
         mDurationOverride = duration;
         mAnimationDelay = delay;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 285b9bc..0314ca2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -242,7 +242,7 @@
         return mStatusBarWindowManager.isShowingWallpaper();
     }
 
-    public void setOccluded(boolean occluded) {
+    public void setOccluded(boolean occluded, boolean animate) {
         if (occluded != mOccluded) {
             mPhoneStatusBar.onKeyguardOccludedChanged(occluded);
         }
@@ -261,9 +261,12 @@
             }
         }
         mOccluded = occluded;
-        mPhoneStatusBar.updateMediaMetaData(false, false);
+        mPhoneStatusBar.updateMediaMetaData(false, animate && !occluded);
         mStatusBarWindowManager.setKeyguardOccluded(occluded);
         reset();
+        if (animate && !occluded) {
+            mPhoneStatusBar.animateKeyguardUnoccluding();
+        }
     }
 
     public boolean isOccluded() {
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 876a33e..5d6ac12 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -43,7 +43,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
-    mockito-target \
+    mockito-target-minus-junit4 \
     SystemUI-proto-tags
 
 LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.car
@@ -54,9 +54,42 @@
 # UI it doesn't own. This is necessary to allow screenshots to be taken
 LOCAL_CERTIFICATE := platform
 
+# Provide jack a list of classes to exclude from code coverage.
+# This is needed because the SystemUITests compile SystemUI source directly, rather than using
+# LOCAL_INSTRUMENTATION_FOR := SystemUI.
+#
+# We want to exclude the test classes from code coverage measurements, but they share the same
+# package as the rest of SystemUI so they can't be easily filtered by package name.
+#
+# Generate a comma separated list of patterns based on the test source files under src/
+# SystemUI classes are in ../src/ so they won't be excluded.
+# Example:
+#   Input files: src/com/android/systemui/Test.java src/com/android/systemui/AnotherTest.java
+#   Generated exclude list: com.android.systemui.Test*,com.android.systemui.AnotherTest*
+
+# Filter all src files under src/ to just java files
+local_java_files := $(filter %.java,$(call all-java-files-under, src))
+# Transform java file names into full class names.
+# This only works if the class name matches the file name and the directory structure
+# matches the package.
+local_classes := $(subst /,.,$(patsubst src/%.java,%,$(local_java_files)))
+local_comma := ,
+local_empty :=
+local_space := $(local_empty) $(local_empty)
+# Convert class name list to jacoco exclude list
+# This appends a * to all classes and replace the space separators with commas.
+jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes)))
+
 LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.systemui.*
-LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := com.android.systemui.tests.*
+LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := com.android.systemui.tests.*,$(jacoco_exclude)
 
 include frameworks/base/packages/SettingsLib/common.mk
 
 include $(BUILD_PACKAGE)
+
+# Reset variables
+local_java_files :=
+local_classes :=
+local_comma :=
+local_space :=
+jacoco_exclude :=
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
index 9f0eb9b..9795027 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
@@ -15,13 +15,24 @@
  */
 package com.android.systemui.qs.external;
 
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.when;
+
 import android.app.Service;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.ServiceInfo;
+import android.net.Uri;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -31,6 +42,7 @@
 import android.service.quicksettings.IQSService;
 import android.service.quicksettings.IQSTileService;
 import android.service.quicksettings.Tile;
+import android.service.quicksettings.TileService;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.ArraySet;
@@ -42,10 +54,6 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TileLifecycleManagerTests extends SysuiTestCase {
@@ -57,10 +65,13 @@
     private TileLifecycleManager mStateManager;
     private final Object mBroadcastLock = new Object();
     private final ArraySet<String> mCallbacks = new ArraySet<>();
+    private final PackageManagerAdapter mMockPackageManagerAdapter =
+            Mockito.mock(PackageManagerAdapter.class);
     private boolean mBound;
 
     @Before
     public void setUp() throws Exception {
+        setPackageEnabled(true);
         mThread = new HandlerThread("TestThread");
         mThread.start();
         mHandler = new Handler(mThread.getLooper());
@@ -68,7 +79,8 @@
         mStateManager = new TileLifecycleManager(mHandler, getContext(),
                 Mockito.mock(IQSService.class), new Tile(),
                 new Intent().setComponent(component),
-                new UserHandle(UserHandle.myUserId()));
+                new UserHandle(UserHandle.myUserId()),
+                mMockPackageManagerAdapter);
         mCallbacks.clear();
         getContext().registerReceiver(mReceiver, new IntentFilter(TILE_UPDATE_BROADCAST));
     }
@@ -82,6 +94,22 @@
         getContext().unregisterReceiver(mReceiver);
     }
 
+    private void setPackageEnabled(boolean enabled) throws Exception {
+        ServiceInfo defaultServiceInfo = null;
+        if (enabled) {
+            defaultServiceInfo = new ServiceInfo();
+            defaultServiceInfo.metaData = new Bundle();
+            defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_ACTIVE_TILE, true);
+        }
+        when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt(), anyInt()))
+                .thenReturn(defaultServiceInfo);
+        when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt()))
+                .thenReturn(defaultServiceInfo);
+        PackageInfo defaultPackageInfo = new PackageInfo();
+        when(mMockPackageManagerAdapter.getPackageInfoAsUser(anyString(), anyInt(), anyInt()))
+                .thenReturn(defaultPackageInfo);
+    }
+
     @Test
     public void testSync() {
         syncWithHandler();
@@ -181,19 +209,22 @@
     }
 
     @Test
-    public void testComponentEnabling() {
+    public void testComponentEnabling() throws Exception {
         mStateManager.onTileAdded();
         mStateManager.onStartListening();
 
-        PackageManager pm = getContext().getPackageManager();
-        pm.setComponentEnabledSetting(new ComponentName(getContext(), FakeTileService.class),
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
-
+        setPackageEnabled(false);
         bindService();
+        // Package not available, should be listening for package changes.
         assertTrue(mStateManager.mReceiverRegistered);
 
-        pm.setComponentEnabledSetting(new ComponentName(getContext(), FakeTileService.class),
-                PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
+        // Package is re-enabled.
+        setPackageEnabled(true);
+        mStateManager.onReceive(
+                mContext,
+                new Intent(
+                        Intent.ACTION_PACKAGE_CHANGED,
+                        Uri.fromParts("package", getContext().getPackageName(), null)));
         waitForCallback("onCreate");
     }
 
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 9d88020..a789157 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -742,6 +742,7 @@
             // Legacy apps in permission review mode trigger a user prompt
             if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
                 Intent intent = new Intent(intentAction);
+                intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                         | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                 try {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 051377c..a739be7 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -838,7 +838,14 @@
         mKeepaliveTracker = new KeepaliveTracker(mHandler);
         mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager,
                 mContext.getSystemService(NotificationManager.class));
-        mLingerMonitor = new LingerMonitor(mContext, mNotifier);
+
+        final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
+                LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT);
+        final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(),
+                Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
+                LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
+        mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
     }
 
     private NetworkRequest createInternetRequestForTransport(int transportType) {
@@ -4721,9 +4728,6 @@
                         if (VDBG) log("   accepting network in place of " + currentNetwork.name());
                         currentNetwork.removeRequest(nri.request.requestId);
                         currentNetwork.lingerRequest(nri.request, now, mLingerDelayMs);
-                        if (isDefaultRequest(nri)) {
-                            mLingerMonitor.noteLingerDefaultNetwork(currentNetwork, newNetwork);
-                        }
                         affectedNetworks.add(currentNetwork);
                     } else {
                         if (VDBG) log("   accepting network in place of null");
@@ -4744,6 +4748,9 @@
                     if (isDefaultRequest(nri)) {
                         isNewDefault = true;
                         oldDefaultNetwork = currentNetwork;
+                        if (currentNetwork != null) {
+                            mLingerMonitor.noteLingerDefaultNetwork(currentNetwork, newNetwork);
+                        }
                     }
                 }
             } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4bce363..146684f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2397,22 +2397,21 @@
                 if (memInfo != null) {
                     updateCpuStatsNow();
                     long nativeTotalPss = 0;
+                    final List<ProcessCpuTracker.Stats> stats;
                     synchronized (mProcessCpuTracker) {
-                        final int N = mProcessCpuTracker.countStats();
-                        for (int j=0; j<N; j++) {
-                            ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(j);
-                            if (st.vsize <= 0 || st.uid >= Process.FIRST_APPLICATION_UID) {
-                                // This is definitely an application process; skip it.
+                        stats = mProcessCpuTracker.getStats( (st)-> {
+                            return st.vsize > 0 && st.uid < Process.FIRST_APPLICATION_UID;
+                        });
+                    }
+                    final int N = stats.size();
+                    for (int j = 0; j < N; j++) {
+                        synchronized (mPidsSelfLocked) {
+                            if (mPidsSelfLocked.indexOfKey(stats.get(j).pid) >= 0) {
+                                // This is one of our own processes; skip it.
                                 continue;
                             }
-                            synchronized (mPidsSelfLocked) {
-                                if (mPidsSelfLocked.indexOfKey(st.pid) >= 0) {
-                                    // This is one of our own processes; skip it.
-                                    continue;
-                                }
-                            }
-                            nativeTotalPss += Debug.getPss(st.pid, null, null);
                         }
+                        nativeTotalPss += Debug.getPss(stats.get(j).pid, null, null);
                     }
                     memInfo.readMemInfo();
                     synchronized (ActivityManagerService.this) {
@@ -16505,21 +16504,24 @@
         }
         updateCpuStatsNow();
         long[] memtrackTmp = new long[1];
+        final List<ProcessCpuTracker.Stats> stats;
+        // Get a list of Stats that have vsize > 0
         synchronized (mProcessCpuTracker) {
-            final int N = mProcessCpuTracker.countStats();
-            for (int i=0; i<N; i++) {
-                ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
-                if (st.vsize > 0) {
-                    long pss = Debug.getPss(st.pid, null, memtrackTmp);
-                    if (pss > 0) {
-                        if (infoMap.indexOfKey(st.pid) < 0) {
-                            ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid,
-                                    ProcessList.NATIVE_ADJ, -1, "native", null);
-                            mi.pss = pss;
-                            mi.memtrack = memtrackTmp[0];
-                            memInfos.add(mi);
-                        }
-                    }
+            stats = mProcessCpuTracker.getStats((st) -> {
+                return st.vsize > 0;
+            });
+        }
+        final int statsCount = stats.size();
+        for (int i = 0; i < statsCount; i++) {
+            ProcessCpuTracker.Stats st = stats.get(i);
+            long pss = Debug.getPss(st.pid, null, memtrackTmp);
+            if (pss > 0) {
+                if (infoMap.indexOfKey(st.pid) < 0) {
+                    ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid,
+                            ProcessList.NATIVE_ADJ, -1, "native", null);
+                    mi.pss = pss;
+                    mi.memtrack = memtrackTmp[0];
+                    memInfos.add(mi);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index dacbcc6..6f7e748 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -126,7 +126,6 @@
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityManagerService.ItemMatcher;
 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
-import com.android.server.wm.TaskGroup;
 import com.android.server.wm.WindowManagerService;
 
 import java.io.FileDescriptor;
@@ -162,8 +161,6 @@
     private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
     private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
 
-    private static final boolean VALIDATE_TOKENS = false;
-
     // Ticks during which we check progress while waiting for an app to launch.
     static final int LAUNCH_TICK = 500;
 
@@ -242,11 +239,6 @@
     private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
 
     /**
-     * Used for validating app tokens with window manager.
-     */
-    final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<>();
-
-    /**
      * List of running activities, sorted by recent usage.
      * The first entry in the list is the least recently used.
      * It contains HistoryRecord objects.
@@ -899,9 +891,6 @@
                 ++i;
             }
         }
-        if (VALIDATE_TOKENS) {
-            validateAppTokensLocked();
-        }
     }
 
     void minimalResumeActivityLocked(ActivityRecord r) {
@@ -1598,11 +1587,6 @@
             return STACK_INVISIBLE;
         }
 
-        final boolean isLockscreenShown = mService.mLockScreenShown == LOCK_SCREEN_SHOWN;
-        if (isLockscreenShown && !StackId.isAllowedOverLockscreen(mStackId)) {
-            return STACK_INVISIBLE;
-        }
-
         final ActivityStack focusedStack = mStackSupervisor.getFocusedStack();
         final int focusedStackId = focusedStack.mStackId;
 
@@ -2561,7 +2545,7 @@
                     // what's left last time.
                     for (int i = next.newIntents.size() - 1; i >= 0; i--) {
                         final Intent intent = next.newIntents.get(i);
-                        if (!ActivityRecord.isMainIntent(intent)) {
+                        if (intent != null && !ActivityRecord.isMainIntent(intent)) {
                             allowSavedSurface = false;
                             break;
                         }
@@ -2768,9 +2752,6 @@
                         task.addActivityToTop(r);
                         r.putInHistory();
                         addConfigOverride(r, task);
-                        if (VALIDATE_TOKENS) {
-                            validateAppTokensLocked();
-                        }
                         ActivityOptions.abort(options);
                         return;
                     }
@@ -2872,33 +2853,7 @@
             // because there is nothing for it to animate on top of.
             addConfigOverride(r, task);
             ActivityOptions.abort(options);
-            options = null;
         }
-        if (VALIDATE_TOKENS) {
-            validateAppTokensLocked();
-        }
-    }
-
-    final void validateAppTokensLocked() {
-        mValidateAppTokens.clear();
-        mValidateAppTokens.ensureCapacity(numActivities());
-        final int numTasks = mTaskHistory.size();
-        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
-            TaskRecord task = mTaskHistory.get(taskNdx);
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-            if (activities.isEmpty()) {
-                continue;
-            }
-            TaskGroup group = new TaskGroup();
-            group.taskId = task.taskId;
-            mValidateAppTokens.add(group);
-            final int numActivities = activities.size();
-            for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
-                final ActivityRecord r = activities.get(activityNdx);
-                group.tokens.add(r.appToken);
-            }
-        }
-        mWindowManager.validateAppTokens(mStackId, mValidateAppTokens);
     }
 
     /**
@@ -3010,10 +2965,6 @@
                 }
 
                 mWindowManager.moveTaskToBottom(targetTask.taskId);
-                if (VALIDATE_TOKENS) {
-                    validateAppTokensLocked();
-                }
-
                 replyChainEnd = -1;
             } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
                 // If the activity should just be removed -- either
@@ -3151,9 +3102,6 @@
                         setAppTask(p, task);
                     }
                     mWindowManager.moveTaskToTop(taskId);
-                    if (VALIDATE_TOKENS) {
-                        validateAppTokensLocked();
-                    }
 
                     // Now we've moved it in to place...  but what if this is
                     // a singleTop activity and we have put it on top of another
@@ -3902,9 +3850,6 @@
         if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
         r.app = null;
         mWindowManager.removeAppToken(r.appToken);
-        if (VALIDATE_TOKENS) {
-            validateAppTokensLocked();
-        }
         final TaskRecord task = r.task;
         if (task != null && task.removeActivity(r)) {
             if (DEBUG_STACK) Slog.i(TAG_STACK,
@@ -4400,10 +4345,6 @@
 
         mStackSupervisor.resumeFocusedStackTopActivityLocked();
         EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
-
-        if (VALIDATE_TOKENS) {
-            validateAppTokensLocked();
-        }
     }
 
     /**
@@ -4518,10 +4459,6 @@
         mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
         mWindowManager.moveTaskToBottom(taskId);
 
-        if (VALIDATE_TOKENS) {
-            validateAppTokensLocked();
-        }
-
         final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
         if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) {
             if (!mService.mBooting && !mService.mBooted) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 0a47e40..8e0fcc1 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2464,7 +2464,7 @@
             // entrance of the new window to be properly animated.
             // Note here we always set the replacing window first, as the flags might be needed
             // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
-            mWindowManager.setReplacingWindow(topActivity.appToken, animate);
+            mWindowManager.setWillReplaceWindow(topActivity.appToken, animate);
         }
 
         mWindowManager.deferSurfaceLayout();
@@ -2506,7 +2506,7 @@
             // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
             // window), we need to clear the replace window settings. Otherwise, we schedule a
             // timeout to remove the old window if the replacing window is not coming in time.
-            mWindowManager.scheduleClearReplacingWindowIfNeeded(topActivity.appToken, !kept);
+            mWindowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
         }
 
         if (!deferResume) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 117457f..bd0d9b8 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -604,6 +604,9 @@
         // If we launched the activity from a no display activity that was launched from the home
         // screen, we also need to start recents to un-minimize the docked stack, since the
         // noDisplay activity will be finished shortly after.
+        // Note that some apps have trampoline activities without noDisplay being set. In that case,
+        // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
+        // that tries to detect that case.
         // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
         // visibility instead of using this flag.
         final boolean noDisplayActivityOverHome = sourceRecord != null
diff --git a/services/core/java/com/android/server/connectivity/LingerMonitor.java b/services/core/java/com/android/server/connectivity/LingerMonitor.java
index 4034877..635db19 100644
--- a/services/core/java/com/android/server/connectivity/LingerMonitor.java
+++ b/services/core/java/com/android/server/connectivity/LingerMonitor.java
@@ -17,15 +17,14 @@
 package com.android.server.connectivity;
 
 import android.app.PendingIntent;
-import android.net.ConnectivityManager;
-import android.net.NetworkCapabilities;
-import android.net.Uri;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.net.NetworkCapabilities;
+import android.os.SystemClock;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.text.TextUtils;
+import android.text.format.DateUtils;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
@@ -33,6 +32,8 @@
 import java.util.Arrays;
 import java.util.HashMap;
 
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.MessageUtils;
 import com.android.server.connectivity.NetworkNotificationManager;
 import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
@@ -52,19 +53,30 @@
     private static final boolean VDBG = false;
     private static final String TAG = LingerMonitor.class.getSimpleName();
 
-    private static final HashMap<String, Integer> sTransportNames = makeTransportToNameMap();
-    private static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName(
+    public static final int DEFAULT_NOTIFICATION_DAILY_LIMIT = 3;
+    public static final long DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS = DateUtils.MINUTE_IN_MILLIS;
+
+    private static final HashMap<String, Integer> TRANSPORT_NAMES = makeTransportToNameMap();
+    @VisibleForTesting
+    public static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName(
             "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
 
-    private static final int NOTIFY_TYPE_NONE = 0;
-    private static final int NOTIFY_TYPE_NOTIFICATION = 1;
-    private static final int NOTIFY_TYPE_TOAST = 2;
+    @VisibleForTesting
+    public static final int NOTIFY_TYPE_NONE         = 0;
+    public static final int NOTIFY_TYPE_NOTIFICATION = 1;
+    public static final int NOTIFY_TYPE_TOAST        = 2;
 
     private static SparseArray<String> sNotifyTypeNames = MessageUtils.findMessageNames(
             new Class[] { LingerMonitor.class }, new String[]{ "NOTIFY_TYPE_" });
 
     private final Context mContext;
     private final NetworkNotificationManager mNotifier;
+    private final int mDailyLimit;
+    private final long mRateLimitMillis;
+
+    private long mFirstNotificationMillis;
+    private long mLastNotificationMillis;
+    private int mNotificationCounter;
 
     /** Current notifications. Maps the netId we switched away from to the netId we switched to. */
     private final SparseIntArray mNotifications = new SparseIntArray();
@@ -72,9 +84,12 @@
     /** Whether we ever notified that we switched away from a particular network. */
     private final SparseBooleanArray mEverNotified = new SparseBooleanArray();
 
-    public LingerMonitor(Context context, NetworkNotificationManager notifier) {
+    public LingerMonitor(Context context, NetworkNotificationManager notifier,
+            int dailyLimit, long rateLimitMillis) {
         mContext = context;
         mNotifier = notifier;
+        mDailyLimit = dailyLimit;
+        mRateLimitMillis = rateLimitMillis;
     }
 
     private static HashMap<String, Integer> makeTransportToNameMap() {
@@ -106,10 +121,11 @@
         return mEverNotified.get(nai.network.netId, false);
     }
 
-    private boolean isNotificationEnabled(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) {
+    @VisibleForTesting
+    public boolean isNotificationEnabled(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) {
         // TODO: Evaluate moving to CarrierConfigManager.
-        String[] notifySwitches = mContext.getResources().getStringArray(
-                com.android.internal.R.array.config_networkNotifySwitches);
+        String[] notifySwitches =
+                mContext.getResources().getStringArray(R.array.config_networkNotifySwitches);
 
         if (VDBG) {
             Log.d(TAG, "Notify on network switches: " + Arrays.toString(notifySwitches));
@@ -122,8 +138,8 @@
                 Log.e(TAG, "Invalid network switch notification configuration: " + notifySwitch);
                 continue;
             }
-            int fromTransport = sTransportNames.get("TRANSPORT_" + transports[0]);
-            int toTransport = sTransportNames.get("TRANSPORT_" + transports[1]);
+            int fromTransport = TRANSPORT_NAMES.get("TRANSPORT_" + transports[0]);
+            int toTransport = TRANSPORT_NAMES.get("TRANSPORT_" + transports[1]);
             if (hasTransport(fromNai, fromTransport) && hasTransport(toNai, toTransport)) {
                 return true;
             }
@@ -133,12 +149,14 @@
     }
 
     private void showNotification(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) {
-        PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
-                mContext, 0, CELLULAR_SETTINGS, PendingIntent.FLAG_CANCEL_CURRENT, null,
-                UserHandle.CURRENT);
-
         mNotifier.showNotification(fromNai.network.netId, NotificationType.NETWORK_SWITCH,
-                fromNai, toNai, pendingIntent, true);
+                fromNai, toNai, createNotificationIntent(), true);
+    }
+
+    @VisibleForTesting
+    protected PendingIntent createNotificationIntent() {
+        return PendingIntent.getActivityAsUser(mContext, 0, CELLULAR_SETTINGS,
+                PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
     }
 
     // Removes any notification that was put up as a result of switching to nai.
@@ -153,41 +171,37 @@
 
     // Notify the user of a network switch using a notification or a toast.
     private void notify(NetworkAgentInfo fromNai, NetworkAgentInfo toNai, boolean forceToast) {
-        boolean notify = false;
-        int notifyType = mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_networkNotifySwitchType);
-
+        int notifyType =
+                mContext.getResources().getInteger(R.integer.config_networkNotifySwitchType);
         if (notifyType == NOTIFY_TYPE_NOTIFICATION && forceToast) {
             notifyType = NOTIFY_TYPE_TOAST;
         }
 
-        switch (notifyType) {
-            case NOTIFY_TYPE_NONE:
-                break;
-            case NOTIFY_TYPE_NOTIFICATION:
-                showNotification(fromNai, toNai);
-                notify = true;
-                break;
-            case NOTIFY_TYPE_TOAST:
-                mNotifier.showToast(fromNai, toNai);
-                notify = true;
-                break;
-            default:
-                Log.e(TAG, "Unknown notify type " + notifyType);
-        }
-
         if (VDBG) {
             Log.d(TAG, "Notify type: " + sNotifyTypeNames.get(notifyType, "" + notifyType));
         }
 
-        if (notify) {
-            if (DBG) {
-                Log.d(TAG, "Notifying switch from=" + fromNai.name() + " to=" + toNai.name() +
-                        " type=" + sNotifyTypeNames.get(notifyType, "unknown(" + notifyType + ")"));
-            }
-            mNotifications.put(fromNai.network.netId, toNai.network.netId);
-            mEverNotified.put(fromNai.network.netId, true);
+        switch (notifyType) {
+            case NOTIFY_TYPE_NONE:
+                return;
+            case NOTIFY_TYPE_NOTIFICATION:
+                showNotification(fromNai, toNai);
+                break;
+            case NOTIFY_TYPE_TOAST:
+                mNotifier.showToast(fromNai, toNai);
+                break;
+            default:
+                Log.e(TAG, "Unknown notify type " + notifyType);
+                return;
         }
+
+        if (DBG) {
+            Log.d(TAG, "Notifying switch from=" + fromNai.name() + " to=" + toNai.name() +
+                    " type=" + sNotifyTypeNames.get(notifyType, "unknown(" + notifyType + ")"));
+        }
+
+        mNotifications.put(fromNai.network.netId, toNai.network.netId);
+        mEverNotified.put(fromNai.network.netId, true);
     }
 
     // The default network changed from fromNai to toNai due to a change in score.
@@ -242,9 +256,18 @@
             return;
         }
 
-        if (isNotificationEnabled(fromNai, toNai)) {
-            notify(fromNai, toNai, forceToast);
-        }
+        // Only show the notification if we switched away because a network became unvalidated, not
+        // because its score changed.
+        // TODO: instead of just skipping notification, keep a note of it, and show it if it becomes
+        // unvalidated.
+        if (fromNai.lastValidated) return;
+
+        if (!isNotificationEnabled(fromNai, toNai)) return;
+
+        final long now = SystemClock.elapsedRealtime();
+        if (isRateLimited(now) || isAboveDailyLimit(now)) return;
+
+        notify(fromNai, toNai, forceToast);
     }
 
     public void noteDisconnect(NetworkAgentInfo nai) {
@@ -253,4 +276,29 @@
         maybeStopNotifying(nai);
         // No need to cancel notifications on nai: NetworkMonitor does that on disconnect.
     }
+
+    private boolean isRateLimited(long now) {
+        final long millisSinceLast = now - mLastNotificationMillis;
+        if (millisSinceLast < mRateLimitMillis) {
+            return true;
+        }
+        mLastNotificationMillis = now;
+        return false;
+    }
+
+    private boolean isAboveDailyLimit(long now) {
+        if (mFirstNotificationMillis == 0) {
+            mFirstNotificationMillis = now;
+        }
+        final long millisSinceFirst = now - mFirstNotificationMillis;
+        if (millisSinceFirst > DateUtils.DAY_IN_MILLIS) {
+            mNotificationCounter = 0;
+            mFirstNotificationMillis = 0;
+        }
+        if (mNotificationCounter >= mDailyLimit) {
+            return true;
+        }
+        mNotificationCounter++;
+        return false;
+    }
 }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 0abd2e7..971989b 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1402,6 +1402,9 @@
                 throw new IllegalArgumentException("width, height, and densityDpi must be "
                         + "greater than 0");
             }
+            if (surface != null && surface.isSingleBuffered()) {
+                throw new IllegalArgumentException("Surface can't be single-buffered");
+            }
 
             if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
                 flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
@@ -1460,6 +1463,9 @@
 
         @Override // Binder call
         public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) {
+            if (surface != null && surface.isSingleBuffered()) {
+                throw new IllegalArgumentException("Surface can't be single-buffered");
+            }
             final long token = Binder.clearCallingIdentity();
             try {
                 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index a39d5c8..4a042da 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -412,7 +412,8 @@
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
             INetworkStatsService networkStats, INetworkManagementService networkManagement) {
         this(context, activityManager, networkStats, networkManagement,
-                NtpTrustedTime.getInstance(context), getSystemDir(), false);
+                AppGlobals.getPackageManager(), NtpTrustedTime.getInstance(context), getSystemDir(),
+                false);
     }
 
     private static File getSystemDir() {
@@ -421,7 +422,7 @@
 
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
             INetworkStatsService networkStats, INetworkManagementService networkManagement,
-            TrustedTime time, File systemDir, boolean suppressDefaultPolicy) {
+            IPackageManager pm, TrustedTime time, File systemDir, boolean suppressDefaultPolicy) {
         mContext = checkNotNull(context, "missing context");
         mActivityManager = checkNotNull(activityManager, "missing activityManager");
         mNetworkStats = checkNotNull(networkStats, "missing networkStats");
@@ -430,7 +431,7 @@
                 Context.DEVICE_IDLE_CONTROLLER));
         mTime = checkNotNull(time, "missing TrustedTime");
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        mIPm = AppGlobals.getPackageManager();
+        mIPm = pm;
 
         HandlerThread thread = new HandlerThread(TAG);
         thread.start();
@@ -509,12 +510,13 @@
             try {
                 app = pm.getApplicationInfoAsUser(pkg, PackageManager.MATCH_SYSTEM_ONLY, userId);
             } catch (PackageManager.NameNotFoundException e) {
-                // Should not happen
-                Slog.wtf(TAG, "No ApplicationInfo for package " + pkg);
+                if (LOGD) Slog.d(TAG, "No ApplicationInfo for package " + pkg);
+                // Ignore it - some apps on allow-in-data-usage-save are optional.
                 continue;
             }
             if (!app.isPrivilegedApp()) {
-                Slog.wtf(TAG, "pm.getApplicationInfoAsUser() returned non-privileged app: " + pkg);
+                Slog.e(TAG, "addDefaultRestrictBackgroundWhitelistUidsUL(): "
+                        + "skipping non-privileged app  " + pkg);
                 continue;
             }
             final int uid = UserHandle.getUid(userId, app.uid);
@@ -524,8 +526,9 @@
                         + "background whitelist. Revoked status: "
                         + mRestrictBackgroundWhitelistRevokedUids.get(uid));
             if (!mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
-                Slog.i(TAG, "adding default package " + pkg + " (uid " + uid + " for user "
-                        + userId + ") to restrict background whitelist");
+                if (LOGD)
+                    Slog.d(TAG, "adding default package " + pkg + " (uid " + uid + " for user "
+                            + userId + ") to restrict background whitelist");
                 setUidPolicyUncheckedUL(uid, POLICY_ALLOW_METERED_BACKGROUND, false);
                 changed = true;
             }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5831284..0b8a347 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -44,6 +44,7 @@
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.Signature;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.FileBridge;
 import android.os.FileUtils;
@@ -271,9 +272,14 @@
         } else {
             mPermissionsAccepted = false;
         }
-        final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE,
-                PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
-        defaultContainerGid = UserHandle.getSharedAppGid(uid);
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE,
+                    PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+            defaultContainerGid = UserHandle.getSharedAppGid(uid);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 
     public SessionInfo generateInfo() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1c99ef3..48b3a54 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -197,6 +197,7 @@
 import android.os.storage.VolumeInfo;
 import android.os.storage.VolumeRecord;
 import android.provider.Settings.Global;
+import android.provider.Settings.Secure;
 import android.security.KeyStore;
 import android.security.SystemKeyStore;
 import android.system.ErrnoException;
@@ -365,6 +366,7 @@
     /** REMOVE. According to Svet, this was only used to reset permissions during development. */
     static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false;
 
+    // STOPSHIP; b/30256615
     private static final boolean DISABLE_EPHEMERAL_APPS = !Build.IS_DEBUGGABLE;
 
     private static final int RADIO_UID = Process.PHONE_UID;
@@ -457,6 +459,8 @@
 
     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
 
+    private static final String PACKAGE_SCHEME = "package";
+
     private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
 
     private static int DEFAULT_EPHEMERAL_HASH_PREFIX_MASK = 0xFFFFF000;
@@ -1119,7 +1123,9 @@
 
     final @Nullable String mRequiredVerifierPackage;
     final @NonNull String mRequiredInstallerPackage;
+    final @NonNull String mRequiredUninstallerPackage;
     final @Nullable String mSetupWizardPackage;
+    final @Nullable String mStorageManagerPackage;
     final @NonNull String mServicesSystemSharedLibraryPackageName;
     final @NonNull String mSharedSystemSharedLibraryPackageName;
 
@@ -2474,6 +2480,9 @@
             }
             mExpectingBetter.clear();
 
+            // Resolve the storage manager.
+            mStorageManagerPackage = getStorageManagerPackageName();
+
             // Resolve protected action filters. Only the setup wizard is allowed to
             // have a high priority filter for these actions.
             mSetupWizardPackage = getSetupWizardPackageName();
@@ -2639,6 +2648,7 @@
             if (!mOnlyCore) {
                 mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr();
                 mRequiredInstallerPackage = getRequiredInstallerLPr();
+                mRequiredUninstallerPackage = getRequiredUninstallerLPr();
                 mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
                 mIntentFilterVerifier = new IntentVerifierProxy(mContext,
                         mIntentFilterVerifierComponent);
@@ -2649,6 +2659,7 @@
             } else {
                 mRequiredVerifierPackage = null;
                 mRequiredInstallerPackage = null;
+                mRequiredUninstallerPackage = null;
                 mIntentFilterVerifierComponent = null;
                 mIntentFilterVerifier = null;
                 mServicesSystemSharedLibraryPackageName = null;
@@ -2729,10 +2740,11 @@
                 UserHandle.USER_SYSTEM);
         if (matches.size() == 1) {
             return matches.get(0).getComponentInfo().packageName;
-        } else {
-            Log.e(TAG, "There should probably be exactly one verifier; found " + matches);
+        } else if (matches.size() == 0) {
+            Log.e(TAG, "There should probably be a verifier, but, none were found");
             return null;
         }
+        throw new RuntimeException("There must be exactly one verifier; found " + matches);
     }
 
     private @NonNull String getRequiredSharedLibraryLPr(String libraryName) {
@@ -2764,6 +2776,22 @@
         }
     }
 
+    private @NonNull String getRequiredUninstallerLPr() {
+        final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        intent.setData(Uri.fromParts(PACKAGE_SCHEME, "foo.bar", null));
+
+        final ResolveInfo resolveInfo = resolveIntent(intent, null,
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM);
+        if (resolveInfo == null ||
+                mResolveActivity.name.equals(resolveInfo.getComponentInfo().name)) {
+            throw new RuntimeException("There must be exactly one uninstaller; found "
+                    + resolveInfo);
+        }
+        return resolveInfo.getComponentInfo().packageName;
+    }
+
     private @NonNull ComponentName getIntentFilterVerifierComponentNameLPr() {
         final Intent intent = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION);
 
@@ -4785,11 +4813,23 @@
                 false, false, false, userId);
     }
 
+    private boolean isEphemeralDisabled() {
+        // ephemeral apps have been disabled across the board
+        if (DISABLE_EPHEMERAL_APPS) {
+            return true;
+        }
+        // system isn't up yet; can't read settings, so, assume no ephemeral apps
+        if (!mSystemReady) {
+            return true;
+        }
+        return Secure.getInt(mContext.getContentResolver(), Secure.WEB_ACTION_ENABLED, 1) == 0;
+    }
+
     private boolean isEphemeralAllowed(
             Intent intent, List<ResolveInfo> resolvedActivities, int userId,
             boolean skipPackageCheck) {
         // Short circuit and return early if possible.
-        if (DISABLE_EPHEMERAL_APPS) {
+        if (isEphemeralDisabled()) {
             return false;
         }
         final int callingUser = UserHandle.getCallingUserId();
@@ -6258,7 +6298,7 @@
 
     @Override
     public ParceledListSlice<EphemeralApplicationInfo> getEphemeralApplications(int userId) {
-        if (DISABLE_EPHEMERAL_APPS) {
+        if (isEphemeralDisabled()) {
             return null;
         }
 
@@ -6282,7 +6322,7 @@
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "isEphemeral");
-        if (DISABLE_EPHEMERAL_APPS) {
+        if (isEphemeralDisabled()) {
             return false;
         }
 
@@ -6300,7 +6340,7 @@
 
     @Override
     public byte[] getEphemeralApplicationCookie(String packageName, int userId) {
-        if (DISABLE_EPHEMERAL_APPS) {
+        if (isEphemeralDisabled()) {
             return null;
         }
 
@@ -6318,7 +6358,7 @@
 
     @Override
     public boolean setEphemeralApplicationCookie(String packageName, byte[] cookie, int userId) {
-        if (DISABLE_EPHEMERAL_APPS) {
+        if (isEphemeralDisabled()) {
             return true;
         }
 
@@ -6336,7 +6376,7 @@
 
     @Override
     public Bitmap getEphemeralApplicationIcon(String packageName, int userId) {
-        if (DISABLE_EPHEMERAL_APPS) {
+        if (isEphemeralDisabled()) {
             return null;
         }
 
@@ -11331,7 +11371,7 @@
                     }
                     for (int id : resolvedUserIds) {
                         final Intent intent = new Intent(action,
-                                pkg != null ? Uri.fromParts("package", pkg, null) : null);
+                                pkg != null ? Uri.fromParts(PACKAGE_SCHEME, pkg, null) : null);
                         if (extras != null) {
                             intent.putExtras(extras);
                         }
@@ -11827,6 +11867,12 @@
             return false;
         }
 
+        if (packageName.equals(mRequiredUninstallerPackage)) {
+            Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+                    + "\": required for package uninstallation");
+            return false;
+        }
+
         if (packageName.equals(mRequiredVerifierPackage)) {
             Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
                     + "\": required for package verification");
@@ -15392,13 +15438,11 @@
         Preconditions.checkNotNull(packageName);
         Preconditions.checkNotNull(observer);
         final int uid = Binder.getCallingUid();
-        if (uid != Process.SHELL_UID && uid != Process.ROOT_UID && uid != Process.SYSTEM_UID
-                && uid != getPackageUid(mRequiredInstallerPackage, 0, UserHandle.getUserId(uid))
-                && !isOrphaned(packageName)
-                && !isCallerSameAsInstaller(uid, packageName)) {
+        if (!isOrphaned(packageName)
+                && !isCallerAllowedToSilentlyUninstall(uid, packageName)) {
             try {
                 final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
-                intent.setData(Uri.fromParts("package", packageName, null));
+                intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null));
                 intent.putExtra(PackageInstaller.EXTRA_CALLBACK, observer.asBinder());
                 observer.onUserActionRequired(intent);
             } catch (RemoteException re) {
@@ -15473,10 +15517,35 @@
         });
     }
 
-    private boolean isCallerSameAsInstaller(int callingUid, String pkgName) {
-        final int installerPkgUid = getPackageUid(getInstallerPackageName(pkgName),
-                0 /* flags */, UserHandle.getUserId(callingUid));
-        return installerPkgUid == callingUid;
+    private boolean isCallerAllowedToSilentlyUninstall(int callingUid, String pkgName) {
+        if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID
+              || callingUid == Process.SYSTEM_UID) {
+            return true;
+        }
+        final int callingUserId = UserHandle.getUserId(callingUid);
+        // If the caller installed the pkgName, then allow it to silently uninstall.
+        if (callingUid == getPackageUid(getInstallerPackageName(pkgName), 0, callingUserId)) {
+            return true;
+        }
+
+        // Allow package verifier to silently uninstall.
+        if (mRequiredVerifierPackage != null &&
+                callingUid == getPackageUid(mRequiredVerifierPackage, 0, callingUserId)) {
+            return true;
+        }
+
+        // Allow package uninstaller to silently uninstall.
+        if (mRequiredUninstallerPackage != null &&
+                callingUid == getPackageUid(mRequiredUninstallerPackage, 0, callingUserId)) {
+            return true;
+        }
+
+        // Allow storage manager to silently uninstall.
+        if (mStorageManagerPackage != null &&
+                callingUid == getPackageUid(mStorageManagerPackage, 0, callingUserId)) {
+            return true;
+        }
+        return false;
     }
 
     private int[] getBlockUninstallForUsers(String packageName, int[] userIds) {
@@ -17691,6 +17760,22 @@
         }
     }
 
+    private @Nullable String getStorageManagerPackageName() {
+        final Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
+
+        final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
+                MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE
+                        | MATCH_DISABLED_COMPONENTS,
+                UserHandle.myUserId());
+        if (matches.size() == 1) {
+            return matches.get(0).getComponentInfo().packageName;
+        } else {
+            Slog.e(TAG, "There should probably be exactly one storage manager; found "
+                    + matches.size() + ": matches=" + matches);
+            return null;
+        }
+    }
+
     @Override
     public void setApplicationEnabledSetting(String appPackageName,
             int newState, int flags, int userId, String callingPackage) {
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 8970556..7d4532f 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -331,9 +331,8 @@
         }
 
         try {
-            final byte[] buf = new byte[20];
-            final int len = Os.getxattr(file.getAbsolutePath(), XATTR_SEAPP_HASH, buf);
-            if ((len == 20) && Arrays.equals(SEAPP_CONTEXTS_HASH, buf)) {
+            final byte[] buf = Os.getxattr(file.getAbsolutePath(), XATTR_SEAPP_HASH);
+            if ((buf.length == 20) && Arrays.equals(SEAPP_CONTEXTS_HASH, buf)) {
                 return false;
             }
         } catch (ErrnoException e) {
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 6f6fd7c..1acc955 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -1151,6 +1151,17 @@
         }
     }
 
+    /** @return true if there's any shortcuts that are not manifest shortcuts. */
+    public boolean hasNonManifestShortcuts() {
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+            if (!si.isDeclaredInManifest()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
         pw.println();
 
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index 79b5c4e..1780058 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -40,7 +40,7 @@
 
     private final ShortcutPackageInfo mPackageInfo;
 
-    protected final ShortcutUser mShortcutUser;
+    protected ShortcutUser mShortcutUser;
 
     protected ShortcutPackageItem(@NonNull ShortcutUser shortcutUser,
             int packageUserId, @NonNull String packageName,
@@ -51,6 +51,13 @@
         mPackageInfo = Preconditions.checkNotNull(packageInfo);
     }
 
+    /**
+     * Change the parent {@link ShortcutUser}.  Need it in the restore code.
+     */
+    public void replaceUser(ShortcutUser user) {
+        mShortcutUser = user;
+    }
+
     public ShortcutUser getUser() {
         return mShortcutUser;
     }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index adf19dc..2c61f75 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -380,6 +380,12 @@
     @GuardedBy("mLock")
     private Exception mLastWtfStacktrace;
 
+    static class InvalidFileFormatException extends Exception {
+        public InvalidFileFormatException(String message, Throwable cause) {
+            super(message, cause);
+        }
+    }
+
     public ShortcutService(Context context) {
         this(context, BackgroundThread.get().getLooper(), /*onyForPackgeManagerApis*/ false);
     }
@@ -961,7 +967,7 @@
         try {
             final ShortcutUser ret = loadUserInternal(userId, in, /* forBackup= */ false);
             return ret;
-        } catch (IOException | XmlPullParserException e) {
+        } catch (IOException | XmlPullParserException | InvalidFileFormatException e) {
             Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
             return null;
         } finally {
@@ -970,7 +976,8 @@
     }
 
     private ShortcutUser loadUserInternal(@UserIdInt int userId, InputStream is,
-            boolean fromBackup) throws XmlPullParserException, IOException {
+            boolean fromBackup) throws XmlPullParserException, IOException,
+            InvalidFileFormatException {
 
         final BufferedInputStream bis = new BufferedInputStream(is);
 
@@ -3170,15 +3177,16 @@
                 wtf("Can't restore: user " + userId + " is locked or not running");
                 return;
             }
-            final ShortcutUser user;
+            // Actually do restore.
+            final ShortcutUser restored;
             final ByteArrayInputStream is = new ByteArrayInputStream(payload);
             try {
-                user = loadUserInternal(userId, is, /* fromBackup */ true);
-            } catch (XmlPullParserException | IOException e) {
+                restored = loadUserInternal(userId, is, /* fromBackup */ true);
+            } catch (XmlPullParserException | IOException | InvalidFileFormatException e) {
                 Slog.w(TAG, "Restoration failed.", e);
                 return;
             }
-            mUsers.put(userId, user);
+            getUserShortcutsLocked(userId).mergeRestoredFile(restored);
 
             // Rescan all packages to re-publish manifest shortcuts and do other checks.
             rescanUpdatedPackagesLocked(userId,
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index c05c66f..5d4bfa4 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -23,12 +23,14 @@
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
+import com.android.server.pm.ShortcutService.InvalidFileFormatException;
 
 import libcore.util.Objects;
 
@@ -164,6 +166,11 @@
         return mPackages.containsKey(packageName);
     }
 
+    private void addPackage(@NonNull ShortcutPackage p) {
+        p.replaceUser(this);
+        mPackages.put(p.getPackageName(), p);
+    }
+
     public ShortcutPackage removePackage(@NonNull String packageName) {
         final ShortcutPackage removed = mPackages.remove(packageName);
 
@@ -179,7 +186,8 @@
         return mLaunchers;
     }
 
-    public void addLauncher(ShortcutLauncher launcher) {
+    private void addLauncher(ShortcutLauncher launcher) {
+        launcher.replaceUser(this);
         mLaunchers.put(PackageWithUser.of(launcher.getPackageUserId(),
                 launcher.getPackageName()), launcher);
     }
@@ -326,13 +334,16 @@
             throws IOException, XmlPullParserException {
         out.startTag(null, TAG_ROOT);
 
-        ShortcutService.writeAttr(out, ATTR_KNOWN_LOCALES, mKnownLocales);
-        ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_TIME,
-                mLastAppScanTime);
-        ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_OS_FINGERPRINT,
-                mLastAppScanOsFingerprint);
+        if (!forBackup) {
+            // Don't have to back them up.
+            ShortcutService.writeAttr(out, ATTR_KNOWN_LOCALES, mKnownLocales);
+            ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_TIME,
+                    mLastAppScanTime);
+            ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_OS_FINGERPRINT,
+                    mLastAppScanOsFingerprint);
 
-        ShortcutService.writeTagValue(out, TAG_LAUNCHER, mLastKnownLauncher);
+            ShortcutService.writeTagValue(out, TAG_LAUNCHER, mLastKnownLauncher);
+        }
 
         // Can't use forEachPackageItem due to the checked exceptions.
         {
@@ -365,54 +376,59 @@
     }
 
     public static ShortcutUser loadFromXml(ShortcutService s, XmlPullParser parser, int userId,
-            boolean fromBackup) throws IOException, XmlPullParserException {
+            boolean fromBackup) throws IOException, XmlPullParserException, InvalidFileFormatException {
         final ShortcutUser ret = new ShortcutUser(s, userId);
 
-        ret.mKnownLocales = ShortcutService.parseStringAttribute(parser,
-                ATTR_KNOWN_LOCALES);
+        try {
+            ret.mKnownLocales = ShortcutService.parseStringAttribute(parser,
+                    ATTR_KNOWN_LOCALES);
 
-        // If lastAppScanTime is in the future, that means the clock went backwards.
-        // Just scan all apps again.
-        final long lastAppScanTime = ShortcutService.parseLongAttribute(parser,
-                ATTR_LAST_APP_SCAN_TIME);
-        final long currentTime = s.injectCurrentTimeMillis();
-        ret.mLastAppScanTime = lastAppScanTime < currentTime ? lastAppScanTime : 0;
-        ret.mLastAppScanOsFingerprint = ShortcutService.parseStringAttribute(parser,
-                ATTR_LAST_APP_SCAN_OS_FINGERPRINT);
-        final int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type != XmlPullParser.START_TAG) {
-                continue;
-            }
-            final int depth = parser.getDepth();
-            final String tag = parser.getName();
+            // If lastAppScanTime is in the future, that means the clock went backwards.
+            // Just scan all apps again.
+            final long lastAppScanTime = ShortcutService.parseLongAttribute(parser,
+                    ATTR_LAST_APP_SCAN_TIME);
+            final long currentTime = s.injectCurrentTimeMillis();
+            ret.mLastAppScanTime = lastAppScanTime < currentTime ? lastAppScanTime : 0;
+            ret.mLastAppScanOsFingerprint = ShortcutService.parseStringAttribute(parser,
+                    ATTR_LAST_APP_SCAN_OS_FINGERPRINT);
+            final int outerDepth = parser.getDepth();
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                if (type != XmlPullParser.START_TAG) {
+                    continue;
+                }
+                final int depth = parser.getDepth();
+                final String tag = parser.getName();
 
-            if (depth == outerDepth + 1) {
-                switch (tag) {
-                    case TAG_LAUNCHER: {
-                        ret.mLastKnownLauncher = ShortcutService.parseComponentNameAttribute(
-                                parser, ATTR_VALUE);
-                        continue;
-                    }
-                    case ShortcutPackage.TAG_ROOT: {
-                        final ShortcutPackage shortcuts = ShortcutPackage.loadFromXml(
-                                s, ret, parser, fromBackup);
+                if (depth == outerDepth + 1) {
+                    switch (tag) {
+                        case TAG_LAUNCHER: {
+                            ret.mLastKnownLauncher = ShortcutService.parseComponentNameAttribute(
+                                    parser, ATTR_VALUE);
+                            continue;
+                        }
+                        case ShortcutPackage.TAG_ROOT: {
+                            final ShortcutPackage shortcuts = ShortcutPackage.loadFromXml(
+                                    s, ret, parser, fromBackup);
 
-                        // Don't use addShortcut(), we don't need to save the icon.
-                        ret.mPackages.put(shortcuts.getPackageName(), shortcuts);
-                        continue;
-                    }
+                            // Don't use addShortcut(), we don't need to save the icon.
+                            ret.mPackages.put(shortcuts.getPackageName(), shortcuts);
+                            continue;
+                        }
 
-                    case ShortcutLauncher.TAG_ROOT: {
-                        ret.addLauncher(
-                                ShortcutLauncher.loadFromXml(parser, ret, userId, fromBackup));
-                        continue;
+                        case ShortcutLauncher.TAG_ROOT: {
+                            ret.addLauncher(
+                                    ShortcutLauncher.loadFromXml(parser, ret, userId, fromBackup));
+                            continue;
+                        }
                     }
                 }
+                ShortcutService.warnForInvalidTag(depth, tag);
             }
-            ShortcutService.warnForInvalidTag(depth, tag);
+        } catch (RuntimeException e) {
+            throw new ShortcutService.InvalidFileFormatException(
+                    "Unable to parse file", e);
         }
         return ret;
     }
@@ -461,6 +477,51 @@
         }
     }
 
+    public void mergeRestoredFile(ShortcutUser restored) {
+        final ShortcutService s = mService;
+        // Note, a restore happens only at the end of setup wizard.  At this point, no apps are
+        // installed from Play Store yet, but it's still possible that system apps have already
+        // published dynamic shortcuts, since some apps do so on BOOT_COMPLETED.
+        // When such a system app has allowbackup=true, then we go ahead and replace all existing
+        // shortcuts with the restored shortcuts.  (Then we'll re-publish manifest shortcuts later
+        // in the call site.)
+        // When such a system app has allowbackup=false, then we'll keep the shortcuts that have
+        // already been published.  So we selectively add restored ShortcutPackages here.
+        //
+        // The same logic applies to launchers, but since launchers shouldn't pin shortcuts
+        // without users interaction it's really not a big deal, so we just clear existing
+        // ShortcutLauncher instances in mLaunchers and add all the restored ones here.
+
+        mLaunchers.clear();
+        restored.forAllLaunchers(sl -> {
+            // If the app is already installed and allowbackup = false, then ignore the restored
+            // data.
+            if (s.isPackageInstalled(sl.getPackageName(), getUserId())
+                    && !s.shouldBackupApp(sl.getPackageName(), getUserId())) {
+                return;
+            }
+            addLauncher(sl);
+        });
+        restored.forAllPackages(sp -> {
+            // If the app is already installed and allowbackup = false, then ignore the restored
+            // data.
+            if (s.isPackageInstalled(sp.getPackageName(), getUserId())
+                    && !s.shouldBackupApp(sp.getPackageName(), getUserId())) {
+                return;
+            }
+
+            final ShortcutPackage previous = getPackageShortcutsIfExists(sp.getPackageName());
+            if (previous != null && previous.hasNonManifestShortcuts()) {
+                Log.w(TAG, "Shortcuts for package " + sp.getPackageName() + " are being restored."
+                        + " Existing non-manifeset shortcuts will be overwritten.");
+            }
+            addPackage(sp);
+        });
+        // Empty the launchers and packages in restored to avoid accidentally using them.
+        restored.mLaunchers.clear();
+        restored.mPackages.clear();
+    }
+
     public void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
         pw.print(prefix);
         pw.print("User: ");
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index bdb138e..5176c06d 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -180,7 +180,8 @@
             UserInfo.FLAG_MANAGED_PROFILE
             | UserInfo.FLAG_EPHEMERAL
             | UserInfo.FLAG_RESTRICTED
-            | UserInfo.FLAG_GUEST;
+            | UserInfo.FLAG_GUEST
+            | UserInfo.FLAG_DEMO;
 
     private static final int MIN_USER_ID = 10;
     // We need to keep process uid within Integer.MAX_VALUE.
@@ -3041,9 +3042,8 @@
      */
     private static int getSerialNumber(File file) throws IOException {
         try {
-            final byte[] buf = new byte[256];
-            final int len = Os.getxattr(file.getAbsolutePath(), XATTR_SERIAL, buf);
-            final String serial = new String(buf, 0, len);
+            final byte[] buf = Os.getxattr(file.getAbsolutePath(), XATTR_SERIAL);
+            final String serial = new String(buf);
             try {
                 return Integer.parseInt(serial);
             } catch (NumberFormatException e) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 4fff6ae..f74febe 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5399,15 +5399,18 @@
         boolean showing = mKeyguardDelegate.isShowing();
         if (wasOccluded && !isOccluded && showing) {
             mKeyguardOccluded = false;
-            mKeyguardDelegate.setOccluded(false);
+            mKeyguardDelegate.setOccluded(false, true /* animate */);
             mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
             if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
                 mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
             }
+            Animation anim = AnimationUtils.loadAnimation(mContext,
+                    com.android.internal.R.anim.wallpaper_open_exit);
+            mWindowManagerFuncs.overridePlayingAppAnimationsLw(anim);
             return true;
         } else if (!wasOccluded && isOccluded && showing) {
             mKeyguardOccluded = true;
-            mKeyguardDelegate.setOccluded(true);
+            mKeyguardDelegate.setOccluded(true, false /* animate */);
             mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
             mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
             return true;
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index e4a9254..2069f24 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -181,7 +181,7 @@
                 mKeyguardService.onBootCompleted();
             }
             if (mKeyguardState.occluded) {
-                mKeyguardService.setOccluded(mKeyguardState.occluded);
+                mKeyguardService.setOccluded(mKeyguardState.occluded, false /* animate */);
             }
             if (!mKeyguardState.enabled) {
                 mKeyguardService.setKeyguardEnabled(mKeyguardState.enabled);
@@ -236,10 +236,10 @@
         }
     }
 
-    public void setOccluded(boolean isOccluded) {
+    public void setOccluded(boolean isOccluded, boolean animate) {
         if (mKeyguardService != null) {
-            if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ")");
-            mKeyguardService.setOccluded(isOccluded);
+            if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ") animate=" + animate);
+            mKeyguardService.setOccluded(isOccluded, animate);
         }
         mKeyguardState.occluded = isOccluded;
     }
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index 5a43568..1d85f34 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -63,9 +63,9 @@
     }
 
     @Override // Binder interface
-    public void setOccluded(boolean isOccluded) {
+    public void setOccluded(boolean isOccluded, boolean animate) {
         try {
-            mService.setOccluded(isOccluded);
+            mService.setOccluded(isOccluded, animate);
         } catch (RemoteException e) {
             Slog.w(TAG , "Remote Exception", e);
         }
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 8aeb626..3075102 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -352,9 +352,17 @@
                         (cropHint.right > options.outWidth ? options.outWidth - cropHint.right : 0),
                         (cropHint.bottom > options.outHeight ? options.outHeight - cropHint.bottom : 0));
 
+                // If the crop hint was larger than the image we just overshot. Patch things up.
+                if (cropHint.left < 0) {
+                    cropHint.left = 0;
+                }
+                if (cropHint.top < 0) {
+                    cropHint.top = 0;
+                }
+
                 // Don't bother cropping if what we're left with is identity
                 needCrop = (options.outHeight > cropHint.height()
-                        && options.outWidth > cropHint.width());
+                        || options.outWidth > cropHint.width());
             }
 
             // scale if the crop height winds up not matching the recommended metrics
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index d4d6f32..e4ec295 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -382,7 +382,7 @@
                 topOpeningAppAnimator != null ? topOpeningAppAnimator.animation : null,
                 topClosingAppAnimator != null ? topClosingAppAnimator.animation : null);
         mService.getDefaultDisplayContentLocked().getDockedDividerController()
-                .notifyAppTransitionStarting();
+                .notifyAppTransitionStarting(openingApps);
 
         // Prolong the start for the transition when docking a task from recents, unless recents
         // ended it already then we don't need to wait.
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 4b1cde7..518b9b5 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -18,25 +18,22 @@
 
 import static android.app.ActivityManager.StackId;
 import static android.view.Display.DEFAULT_DISPLAY;
+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.WindowManagerPolicy.TRANSIT_ENTER;
-import static android.view.WindowManagerPolicy.TRANSIT_EXIT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.NOTIFY_ACTIVITY_DRAWN;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
 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.logWithStack;
 
 import com.android.server.input.InputApplicationHandle;
@@ -49,12 +46,12 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Message;
-import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.Slog;
 import android.view.IApplicationToken;
 import android.view.View;
 import android.view.WindowManager;
+import android.view.animation.Animation;
 
 import java.io.PrintWriter;
 import java.util.ArrayDeque;
@@ -130,6 +127,8 @@
     boolean startingDisplayed;
     boolean startingMoved;
     boolean firstWindowDrawn;
+    private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
+            new WindowState.UpdateReportedVisibilityResults();
 
     // Input application handle used by the input dispatcher.
     final InputApplicationHandle mInputApplicationHandle;
@@ -151,43 +150,19 @@
     ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
     ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
 
-    AppWindowToken(WindowManagerService service, IApplicationToken _token, boolean _voiceInteraction) {
-        super(service, _token.asBinder(), WindowManager.LayoutParams.TYPE_APPLICATION, true);
-        appToken = _token;
+    AppWindowToken(WindowManagerService service, IApplicationToken token, boolean _voiceInteraction) {
+        super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true);
+        appToken = token;
         voiceInteraction = _voiceInteraction;
         mInputApplicationHandle = new InputApplicationHandle(this);
         mAppAnimator = new AppWindowAnimator(this, service);
     }
 
-    void sendAppVisibilityToClients() {
-        final int N = windows.size();
-        for (int i=0; i<N; i++) {
-            WindowState win = windows.get(i);
-            if (win == startingWindow && clientHidden) {
-                // Don't hide the starting window.
-                continue;
-            }
-            try {
-                if (DEBUG_VISIBILITY) Slog.v(TAG,
-                        "Setting visibility of " + win + ": " + (!clientHidden));
-                win.mClient.dispatchAppVisibility(!clientHidden);
-            } catch (RemoteException e) {
-            }
-        }
-    }
-
-    void setVisibleBeforeClientHidden() {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState w = windows.get(i);
-            w.setVisibleBeforeClientHidden();
-        }
-    }
-
     void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
         firstWindowDrawn = true;
 
         // We now have a good window to show, remove dead placeholders
-        removeAllDeadWindows();
+        removeDeadWindows();
 
         if (startingData != null) {
             if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG, "Finish starting "
@@ -207,50 +182,21 @@
             return;
         }
 
-        int numInteresting = 0;
-        int numVisible = 0;
-        int numDrawn = 0;
-        boolean nowGone = true;
+        if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
+        final int count = mChildren.size();
 
-        if (DEBUG_VISIBILITY) Slog.v(TAG,
-                "Update reported visibility: " + this);
-        final int N = windows.size();
-        for (int i=0; i<N; i++) {
-            WindowState win = windows.get(i);
-            if (win == startingWindow || win.mAppFreezing
-                    || win.mViewVisibility != View.VISIBLE
-                    || win.mAttrs.type == TYPE_APPLICATION_STARTING
-                    || win.mDestroying) {
-                continue;
-            }
-            if (DEBUG_VISIBILITY) {
-                Slog.v(TAG, "Win " + win + ": isDrawn="
-                        + win.isDrawnLw()
-                        + ", isAnimationSet=" + win.mWinAnimator.isAnimationSet());
-                if (!win.isDrawnLw()) {
-                    Slog.v(TAG, "Not displayed: s=" +
-                            win.mWinAnimator.mSurfaceController
-                            + " pv=" + win.mPolicyVisibility
-                            + " mDrawState=" + win.mWinAnimator.mDrawState
-                            + " ph=" + win.isParentWindowHidden()
-                            + " th="
-                            + (win.mAppToken != null
-                                    ? win.mAppToken.hiddenRequested : false)
-                            + " a=" + win.mWinAnimator.mAnimating);
-                }
-            }
-            numInteresting++;
-            if (win.isDrawnLw()) {
-                numDrawn++;
-                if (!win.mWinAnimator.isAnimationSet()) {
-                    numVisible++;
-                }
-                nowGone = false;
-            } else if (win.mWinAnimator.isAnimationSet()) {
-                nowGone = false;
-            }
+        mReportedVisibilityResults.reset();
+
+        for (int i = 0; i < count; i++) {
+            final WindowState win = (WindowState) mChildren.get(i);
+            win.updateReportedVisibility(mReportedVisibilityResults);
         }
 
+        int numInteresting = mReportedVisibilityResults.numInteresting;
+        int numVisible = mReportedVisibilityResults.numVisible;
+        int numDrawn = mReportedVisibilityResults.numDrawn;
+        boolean nowGone = mReportedVisibilityResults.nowGone;
+
         boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
         boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
         if (!nowGone) {
@@ -266,23 +212,16 @@
                 + numInteresting + " visible=" + numVisible);
         if (nowDrawn != reportedDrawn) {
             if (nowDrawn) {
-                Message m = mService.mH.obtainMessage(
-                        H.REPORT_APPLICATION_TOKEN_DRAWN, this);
-                mService.mH.sendMessage(m);
+                mService.mH.obtainMessage(H.REPORT_APPLICATION_TOKEN_DRAWN, this).sendToTarget();
             }
             reportedDrawn = nowDrawn;
         }
         if (nowVisible != reportedVisible) {
-            if (DEBUG_VISIBILITY) Slog.v(
-                    TAG, "Visibility changed in " + this
-                    + ": vis=" + nowVisible);
+            if (DEBUG_VISIBILITY) Slog.v(TAG,
+                    "Visibility changed in " + this + ": vis=" + nowVisible);
             reportedVisible = nowVisible;
-            Message m = mService.mH.obtainMessage(
-                    H.REPORT_APPLICATION_TOKEN_WINDOWS,
-                    nowVisible ? 1 : 0,
-                    nowGone ? 1 : 0,
-                    this);
-            mService.mH.sendMessage(m);
+            mService.mH.obtainMessage(H.REPORT_APPLICATION_TOKEN_WINDOWS,
+                    nowVisible ? 1 : 0, nowGone ? 1 : 0, this).sendToTarget();
         }
     }
 
@@ -327,48 +266,10 @@
                 changed = true;
             }
 
-            final int windowsCount = windows.size();
+            final int windowsCount = mChildren.size();
             for (int i = 0; i < windowsCount; i++) {
-                final WindowState win = windows.get(i);
-                if (win == startingWindow) {
-                    // Starting window that's exiting will be removed when the animation finishes.
-                    // Mark all relevant flags for that onExitAnimationDone will proceed all the way
-                    // to actually remove it.
-                    if (!visible && win.isVisibleNow() && mAppAnimator.isAnimating()) {
-                        win.mAnimatingExit = true;
-                        win.mRemoveOnExit = true;
-                        win.mWindowRemovalAllowed = true;
-                    }
-                    continue;
-                }
-
-                //Slog.i(TAG_WM, "Window " + win + ": vis=" + win.isVisible());
-                //win.dump("  ");
-                if (visible) {
-                    if (!win.isVisibleNow()) {
-                        if (!runningAppAnimation) {
-                            win.mWinAnimator.applyAnimationLocked(TRANSIT_ENTER, true);
-                            //TODO (multidisplay): Magnification is supported only for the default
-                            if (accessibilityController != null
-                                    && win.getDisplayId() == DEFAULT_DISPLAY) {
-                                accessibilityController.onWindowTransitionLocked(win, TRANSIT_ENTER);
-                            }
-                        }
-                        changed = true;
-                        win.setDisplayLayoutNeeded();
-                    }
-                } else if (win.isVisibleNow()) {
-                    if (!runningAppAnimation) {
-                        win.mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
-                        //TODO (multidisplay): Magnification is supported only for the default
-                        if (accessibilityController != null
-                                && win.getDisplayId() == DEFAULT_DISPLAY) {
-                            accessibilityController.onWindowTransitionLocked(win,TRANSIT_EXIT);
-                        }
-                    }
-                    changed = true;
-                    win.setDisplayLayoutNeeded();
-                }
+                final WindowState win = (WindowState) mChildren.get(i);
+                changed |= win.onAppVisibilityChanged(visible, runningAppAnimation);
             }
 
             hidden = hiddenRequested = !visible;
@@ -376,12 +277,11 @@
             if (!visible) {
                 stopFreezingScreen(true, true);
             } else {
-                // If we are being set visible, and the starting window is
-                // not yet displayed, then make sure it doesn't get displayed.
-                WindowState swin = startingWindow;
-                if (swin != null && !swin.isDrawnLw()) {
-                    swin.mPolicyVisibility = false;
-                    swin.mPolicyVisibilityAfterAnim = false;
+                // If we are being set visible, and the starting window is not yet displayed,
+                // then make sure it doesn't get displayed.
+                if (startingWindow != null && !startingWindow.isDrawnLw()) {
+                    startingWindow.mPolicyVisibility = false;
+                    startingWindow.mPolicyVisibilityAfterAnim = false;
                 }
             }
 
@@ -403,8 +303,8 @@
             delayed = true;
         }
 
-        for (int i = windows.size() - 1; i >= 0 && !delayed; i--) {
-            if (windows.get(i).mWinAnimator.isWindowAnimationSet()) {
+        for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
+            if (((WindowState) mChildren.get(i)).isWindowAnimationSet()) {
                 delayed = true;
             }
         }
@@ -431,12 +331,14 @@
 
     WindowState findMainWindow() {
         WindowState candidate = null;
-        int j = windows.size();
+        int j = mChildren.size();
         while (j > 0) {
             j--;
-            WindowState win = windows.get(j);
-            if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
-                    || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
+            final WindowState win = (WindowState) mChildren.get(j);
+            final int type = win.mAttrs.type;
+            // No need to loop through child window as base application and starting types can't be
+            // child windows.
+            if (type == TYPE_BASE_APPLICATION || type == TYPE_APPLICATION_STARTING) {
                 // In cases where there are multiple windows, we prefer the non-exiting window. This
                 // happens for example when replacing windows during an activity relaunch. When
                 // constructing the animation, we want the new window, not the exiting one.
@@ -454,34 +356,6 @@
         return StackId.canReceiveKeys(mTask.mStack.mStackId) || mAlwaysFocusable;
     }
 
-    boolean isVisible() {
-        final int N = windows.size();
-        for (int i=0; i<N; i++) {
-            WindowState win = windows.get(i);
-            // If we're animating with a saved surface, we're already visible.
-            // Return true so that the alpha doesn't get cleared.
-            if (!win.mAppFreezing
-                    && (win.mViewVisibility == View.VISIBLE || win.isAnimatingWithSavedSurface()
-                            || (win.mWinAnimator.isAnimationSet()
-                                    && !mService.mAppTransition.isTransitionSet()))
-                    && !win.mDestroying
-                    && win.isDrawnLw()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    boolean isVisibleForUser() {
-        for (int j = windows.size() - 1; j >= 0; j--) {
-            final WindowState w = windows.get(j);
-            if (!w.isHiddenFromUserLocked()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     void removeAppFromTaskLocked() {
         mIsExiting = false;
         removeAllWindows();
@@ -499,37 +373,9 @@
 
     void clearAnimatingFlags() {
         boolean wallpaperMightChange = false;
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState win = windows.get(i);
-            // We don't want to clear it out for windows that get replaced, because the
-            // animation depends on the flag to remove the replaced window.
-            //
-            // We also don't clear the mAnimatingExit flag for windows which have the
-            // mRemoveOnExit flag. This indicates an explicit remove request has been issued
-            // by the client. We should let animation proceed and not clear this flag or
-            // they won't eventually be removed by WindowStateAnimator#finishExit.
-            if (!win.mWillReplaceWindow && !win.mRemoveOnExit) {
-                // Clear mAnimating flag together with mAnimatingExit. When animation
-                // changes from exiting to entering, we need to clear this flag until the
-                // new animation gets applied, so that isAnimationStarting() becomes true
-                // until then.
-                // Otherwise applySurfaceChangesTransaction will faill to skip surface
-                // placement for this window during this period, one or more frame will
-                // show up with wrong position or scale.
-                if (win.mAnimatingExit) {
-                    win.mAnimatingExit = false;
-                    wallpaperMightChange = true;
-                }
-                if (win.mWinAnimator.mAnimating) {
-                    win.mWinAnimator.mAnimating = false;
-                    wallpaperMightChange = true;
-                }
-                if (win.mDestroying) {
-                    win.mDestroying = false;
-                    mService.mDestroySurface.remove(win);
-                    wallpaperMightChange = true;
-                }
-            }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = (WindowState) mChildren.get(i);
+            wallpaperMightChange |= win.clearAnimatingFlags();
         }
         if (wallpaperMightChange) {
             requestUpdateWallpaperIfNeeded();
@@ -549,42 +395,18 @@
      * others so that they are ready to be reused. If set to false (common case), destroy all
      * surfaces that's eligible, if the app is already stopped.
      */
-
     private void destroySurfaces(boolean cleanupOnResume) {
-        final ArrayList<WindowState> allWindows = (ArrayList<WindowState>) windows.clone();
         final DisplayContentList displayList = new DisplayContentList();
-        for (int i = allWindows.size() - 1; i >= 0; i--) {
-            final WindowState win = allWindows.get(i);
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = (WindowState) mChildren.get(i);
+            final boolean destroyed = win.destroySurface(cleanupOnResume, mAppStopped);
 
-            if (!(mAppStopped || win.mWindowRemovalAllowed || cleanupOnResume)) {
-                continue;
+            if (destroyed) {
+                final DisplayContent displayContent = win.getDisplayContent();
+                if (displayContent != null && !displayList.contains(displayContent)) {
+                    displayList.add(displayContent);
+                }
             }
-
-            win.mWinAnimator.destroyPreservedSurfaceLocked();
-
-            if (!win.mDestroying) {
-                continue;
-            }
-
-            if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + win
-                    + " destroySurfaces: mAppStopped=" + mAppStopped
-                    + " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed
-                    + " win.mRemoveOnExit=" + win.mRemoveOnExit);
-
-            if (!cleanupOnResume || win.mRemoveOnExit) {
-                win.destroyOrSaveSurface();
-            }
-            if (win.mRemoveOnExit) {
-                win.remove();
-            }
-            final DisplayContent displayContent = win.getDisplayContent();
-            if (displayContent != null && !displayList.contains(displayContent)) {
-                displayList.add(displayContent);
-            }
-            if (cleanupOnResume) {
-                win.requestUpdateWallpaperIfNeeded();
-            }
-            win.mDestroying = false;
         }
         for (int i = 0; i < displayList.size(); i++) {
             final DisplayContent displayContent = displayList.get(i);
@@ -634,9 +456,9 @@
         return allDrawn;
     }
 
-    boolean canRestoreSurfaces() {
-        for (int i = windows.size() -1; i >= 0; i--) {
-            final WindowState w = windows.get(i);
+    private boolean canRestoreSurfaces() {
+        for (int i = mChildren.size() -1; i >= 0; i--) {
+            final WindowState w = (WindowState) mChildren.get(i);
             if (w.canRestoreSurface()) {
                 return true;
             }
@@ -644,10 +466,10 @@
         return false;
     }
 
-    void clearVisibleBeforeClientHidden() {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState w = windows.get(i);
-            w.clearVisibleBeforeClientHidden();
+    private void clearWasVisibleBeforeClientHidden() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = (WindowState) mChildren.get(i);
+            w.clearWasVisibleBeforeClientHidden();
         }
     }
 
@@ -656,8 +478,8 @@
      * animating with saved surface.
      */
     boolean isAnimatingInvisibleWithSavedSurface() {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState w = windows.get(i);
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = (WindowState) mChildren.get(i);
             if (w.isAnimatingInvisibleWithSavedSurface()) {
                 return true;
             }
@@ -670,68 +492,50 @@
      * with a saved surface, and mark them destroying.
      */
     void stopUsingSavedSurfaceLocked() {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState w = windows.get(i);
-            if (w.isAnimatingInvisibleWithSavedSurface()) {
-                if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG,
-                        "stopUsingSavedSurfaceLocked: " + w);
-                w.clearAnimatingWithSavedSurface();
-                w.mDestroying = true;
-                w.mWinAnimator.hide("stopUsingSavedSurfaceLocked");
-                mService.mWallpaperControllerLocked.hideWallpapers(w);
-            }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = (WindowState) mChildren.get(i);
+            w.stopUsingSavedSurface();
         }
         destroySurfaces();
     }
 
     void markSavedSurfaceExiting() {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState w = windows.get(i);
-            if (w.isAnimatingInvisibleWithSavedSurface()) {
-                w.mAnimatingExit = true;
-                w.mWinAnimator.mAnimating = true;
-            }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = (WindowState) mChildren.get(i);
+            w.markSavedSurfaceExiting();
         }
     }
 
-    void restoreSavedSurfaces() {
+    void restoreSavedSurfaceForInterestingWindows() {
         if (!canRestoreSurfaces()) {
-            clearVisibleBeforeClientHidden();
+            clearWasVisibleBeforeClientHidden();
             return;
         }
-        // Check if we have enough drawn windows to mark allDrawn= true.
-        int numInteresting = 0;
-        int numDrawn = 0;
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            WindowState w = windows.get(i);
-            if (w != startingWindow && !w.mAppDied && w.wasVisibleBeforeClientHidden()
-                    && (!mAppAnimator.freezingScreen || !w.mAppFreezing)) {
-                numInteresting++;
-                if (w.hasSavedSurface()) {
-                    w.restoreSavedSurface();
-                }
-                if (w.isDrawnLw()) {
-                    numDrawn++;
-                }
-            }
+
+        // Check if all interesting windows are drawn and we can mark allDrawn=true.
+        int interestingNotDrawn = -1;
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = (WindowState) mChildren.get(i);
+            interestingNotDrawn = w.restoreSavedSurfaceForInterestingWindow();
         }
 
         if (!allDrawn) {
-            allDrawn = (numInteresting > 0) && (numInteresting == numDrawn);
+            allDrawn = (interestingNotDrawn == 0);
             if (allDrawn) {
                 mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
             }
         }
-        clearVisibleBeforeClientHidden();
+        clearWasVisibleBeforeClientHidden();
 
         if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG,
-                "restoreSavedSurfaces: " + this + " allDrawn=" + allDrawn
-                + " numInteresting=" + numInteresting + " numDrawn=" + numDrawn);
+                "restoreSavedSurfaceForInterestingWindows: " + this + " allDrawn=" + allDrawn
+                + " interestingNotDrawn=" + interestingNotDrawn);
     }
 
     void destroySavedSurfaces() {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            WindowState win = windows.get(i);
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = (WindowState) mChildren.get(i);
             win.destroySavedSurface();
         }
     }
@@ -750,88 +554,83 @@
         if (startingWindow == win) {
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
             mService.scheduleRemoveStartingWindowLocked(this);
-        } else if (windows.size() == 0 && startingData != null) {
+        } else if (mChildren.size() == 0 && startingData != null) {
             // If this is the last window and we had requested a starting transition window,
             // well there is no point now.
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingWindow");
             startingData = null;
-        } else if (windows.size() == 1 && startingView != null) {
+        } else if (mChildren.size() == 1 && startingView != null) {
             // If this is the last window except for a starting transition window,
             // we need to get rid of the starting transition.
             mService.scheduleRemoveStartingWindowLocked(this);
         }
     }
 
-    void removeAllDeadWindows() {
-        for (int winNdx = windows.size() - 1; winNdx >= 0;
-            // WindowState#removeIfPossible() at bottom of loop may remove multiple entries from
-            // windows if the window to be removed has child windows. It also may
-            // not remove any windows from windows at all if win is exiting and
-            // currently animating away. This ensures that winNdx is monotonically decreasing
-            // and never beyond windows bounds.
-            winNdx = Math.min(winNdx - 1, windows.size() - 1)) {
-            WindowState win = windows.get(winNdx);
+    void removeDeadWindows() {
+        for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
+            WindowState win = (WindowState) mChildren.get(winNdx);
             if (win.mAppDied) {
                 if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.w(TAG,
-                        "removeAllDeadWindows: " + win);
+                        "removeDeadWindows: " + win);
                 // Set mDestroying, we don't want any animation or delayed removal here.
                 win.mDestroying = true;
+                // Also removes child windows.
                 win.removeIfPossible();
             }
         }
     }
 
     boolean hasWindowsAlive() {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            if (!windows.get(i).mAppDied) {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            // No need to loop through child windows as the answer should be the same as that of the
+            // parent window.
+            if (!((WindowState) mChildren.get(i)).mAppDied) {
                 return true;
             }
         }
         return false;
     }
 
-    void setReplacingWindows(boolean animate) {
+    void setWillReplaceWindows(boolean animate) {
         if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
                 "Marking app token " + this + " with replacing windows.");
 
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState w = windows.get(i);
-            w.setReplacing(animate);
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = (WindowState) mChildren.get(i);
+            w.setWillReplaceWindow(animate);
         }
         if (animate) {
             // Set-up dummy animation so we can start treating windows associated with this
             // token like they are in transition before the new app window is ready for us to
             // run the real transition animation.
             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
-                    "setReplacingWindow() Setting dummy animation on: " + this);
+                    "setWillReplaceWindow() Setting dummy animation on: " + this);
             mAppAnimator.setDummyAnimation();
         }
     }
 
-    void setReplacingChildren() {
+    void setWillReplaceChildWindows() {
         if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Marking app token " + this
                 + " with replacing child windows.");
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState w = windows.get(i);
-            if (w.shouldBeReplacedWithChildren()) {
-                w.setReplacing(false /* animate */);
-            }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = (WindowState) mChildren.get(i);
+            w.setWillReplaceChildWindows();
         }
     }
 
-    void resetReplacingWindows() {
+    void clearWillReplaceWindows() {
         if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM,
                 "Resetting app token " + this + " of replacing window marks.");
 
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState w = windows.get(i);
-            w.resetReplacing();
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = (WindowState) mChildren.get(i);
+            w.clearWillReplaceWindow();
         }
     }
 
     void requestUpdateWallpaperIfNeeded() {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState w = windows.get(i);
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState w = (WindowState) mChildren.get(i);
             w.requestUpdateWallpaperIfNeeded();
         }
     }
@@ -870,49 +669,31 @@
     void addWindow(WindowState w) {
         super.addWindow(w);
 
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState candidate = windows.get(i);
-            if (candidate.mWillReplaceWindow && candidate.mReplacingWindow == null
-                    && candidate.getWindowTag().toString().equals(w.getWindowTag().toString())) {
+        boolean gotReplacementWindow = false;
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState candidate = (WindowState) mChildren.get(i);
+            gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
+        }
 
-                candidate.mReplacingWindow = w;
-                w.mSkipEnterAnimationForSeamlessReplacement = !candidate.mAnimateReplacingWindow;
-                // if we got a replacement window, reset the timeout to give drawing more time
-                mService.scheduleReplacingWindowTimeouts(this);
-            }
+        // if we got a replacement window, reset the timeout to give drawing more time
+        if (gotReplacementWindow) {
+            mService.scheduleWindowReplacementTimeouts(this);
         }
     }
 
     boolean waitingForReplacement() {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            WindowState candidate = windows.get(i);
-            if (candidate.mWillReplaceWindow) {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState candidate = (WindowState) mChildren.get(i);
+            if (candidate.waitingForReplacement()) {
                 return true;
             }
         }
         return false;
     }
 
-    void clearTimedoutReplacesLocked() {
-        for (int i = windows.size() - 1; i >= 0;
-             // WindowState#remove() at bottom of loop may remove multiple entries from windows if
-             // the window to be removed has child windows. It also may not remove any windows from
-             // windows at all if win is exiting and currently animating away. This ensures that
-             // winNdx is monotonically decreasing and never beyond windows bounds.
-             i = Math.min(i - 1, windows.size() - 1)) {
-            final WindowState candidate = windows.get(i);
-            if (!candidate.mWillReplaceWindow) {
-                continue;
-            }
-            candidate.mWillReplaceWindow = false;
-            if (candidate.mReplacingWindow != null) {
-                candidate.mReplacingWindow.mSkipEnterAnimationForSeamlessReplacement = false;
-            }
-            // Since the window already timed out, remove it immediately now.
-            // Use WindowState#remove() instead of WindowState#removeIfPossible(), as the latter
-            // delays removal on certain conditions, which will leave the stale window in the
-            // stack and marked mWillReplaceWindow=false, so the window will never be removed.
-            candidate.remove();
+    void onWindowReplacementTimeout() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            ((WindowState) mChildren.get(i)).onWindowReplacementTimeout();
         }
     }
 
@@ -952,16 +733,9 @@
         if (!mFrozenMergedConfig.isEmpty()) {
             mFrozenMergedConfig.remove();
         }
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState win = windows.get(i);
-            if (!win.mHasSurface) {
-                continue;
-            }
-            win.mLayoutNeeded = true;
-            win.setDisplayLayoutNeeded();
-            if (!mService.mResizingWindows.contains(win)) {
-                mService.mResizingWindows.add(win);
-            }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = (WindowState) mChildren.get(i);
+            win.onUnfreezeBounds();
         }
         mService.mWindowPlacerLocked.performSurfacePlacement();
     }
@@ -996,115 +770,36 @@
         }
     }
 
+    /**
+     * See {@link WindowManagerService#overridePlayingAppAnimationsLw}
+     */
+    void overridePlayingAppAnimations(Animation a) {
+        if (mAppAnimator.isAnimating()) {
+            final WindowState win = findMainWindow();
+            final int width = win.mContainingFrame.width();
+            final int height = win.mContainingFrame.height();
+            mAppAnimator.setAnimation(a, width, height, false, STACK_CLIP_NONE);
+        }
+    }
+
     void resetJustMovedInStack() {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            windows.get(i).resetJustMovedInStack();
-        }
-    }
-
-    void setWaitingForDrawnIfResizingChanged() {
-        for (int i = windows.size() - 1; i >= 0; --i) {
-            final WindowState win = windows.get(i);
-            if (win.isDragResizeChanged()) {
-                mService.mWaitingForDrawn.add(win);
-            }
-        }
-    }
-
-    void resizeWindows() {
-        final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
-        // Some windows won't go through the resizing process, if they don't have a surface, so
-        // destroy all saved surfaces here.
-        destroySavedSurfaces();
-
-        for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-            final WindowState win = windows.get(winNdx);
-            if (win.mHasSurface && !resizingWindows.contains(win)) {
-                if (DEBUG_RESIZE) Slog.d(TAG, "resizeWindows: Resizing " + win);
-                resizingWindows.add(win);
-
-                // If we are not drag resizing, force recreating of a new surface so updating
-                // the content and positioning that surface will be in sync.
-                //
-                // As we use this flag as a hint to freeze surface boundary updates,
-                // we'd like to only apply this to TYPE_BASE_APPLICATION,
-                // windows of TYPE_APPLICATION (or TYPE_DRAWN_APPLICATION) like dialogs,
-                // could appear to not be drag resizing while they resize, but we'd
-                // still like to manipulate their frame to update crop, etc...
-                //
-                // Anyway we don't need to synchronize position and content updates for these
-                // windows since they aren't at the base layer and could be moved around anyway.
-                if (!win.computeDragResizing() && win.mAttrs.type == TYPE_BASE_APPLICATION &&
-                        !mTask.mStack.getBoundsAnimating() && !win.isGoneForLayoutLw() &&
-                        !mTask.inPinnedWorkspace()) {
-                    win.setResizedWhileNotDragResizing(true);
-                }
-            }
-            if (win.isGoneForLayoutLw()) {
-                win.mResizedWhileGone = true;
-            }
-        }
-    }
-
-    void moveWindows() {
-        for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-            final WindowState win = windows.get(winNdx);
-            if (DEBUG_RESIZE) Slog.d(TAG, "moveWindows: Moving " + win);
-            win.mMovedByResize = true;
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            ((WindowState) mChildren.get(i)).resetJustMovedInStack();
         }
     }
 
     void notifyMovedInStack() {
-        for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-            final WindowState win = windows.get(winNdx);
+        for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
+            final WindowState win = (WindowState) mChildren.get(winNdx);
             win.notifyMovedInStack();
         }
     }
 
-    void resetDragResizingChangeReported() {
-        for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-            final WindowState win = windows.get(winNdx);
-            win.resetDragResizingChangeReported();
-        }
-    }
-
-    void detachDisplay() {
-        boolean doAnotherLayoutPass = false;
-        for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-            // We are in the middle of changing the state of displays/stacks/tasks. We need
-            // to finish that, before we let layout interfere with it.
-            windows.get(winNdx).removeIfPossible();
-            doAnotherLayoutPass = true;
-        }
-        if (doAnotherLayoutPass) {
-            mService.mWindowPlacerLocked.requestTraversal();
-        }
-    }
-
-    void forceWindowsScaleableInTransaction(boolean force) {
-        for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-            final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
-            if (winAnimator == null || !winAnimator.hasSurface()) {
-                continue;
-            }
-            winAnimator.mSurfaceController.forceScaleableInTransaction(force);
-        }
-    }
-
-    boolean isAnimating() {
-        for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
-            final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
-            if (winAnimator.isAnimationSet() || winAnimator.mWin.mAnimatingExit) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     void setAppLayoutChanges(int changes, String reason, int displayId) {
         final WindowAnimator windowAnimator = mAppAnimator.mAnimator;
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            if (displayId == windows.get(i).getDisplayId()) {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            // Child windows will be on the same display as their parents.
+            if (displayId == ((WindowState) mChildren.get(i)).getDisplayId()) {
                 windowAnimator.setPendingLayoutChanges(displayId, changes);
                 if (DEBUG_LAYOUT_REPEATS) {
                     mService.mWindowPlacerLocked.debugLayoutRepeats(
@@ -1116,19 +811,18 @@
     }
 
     void removeReplacedWindowIfNeeded(WindowState replacement) {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState win = windows.get(i);
-            if (win.mWillReplaceWindow && win.mReplacingWindow == replacement
-                    && replacement.hasDrawnLw()) {
-                replacement.mSkipEnterAnimationForSeamlessReplacement = false;
-                win.removeReplacedWindow();
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = (WindowState) mChildren.get(i);
+            if (win.removeReplacedWindowIfNeeded(replacement)) {
+                return;
             }
         }
     }
 
     void startFreezingScreen() {
         if (DEBUG_ORIENTATION) logWithStack(TAG, "Set freezing of " + appToken + ": hidden="
-                + hidden + " freezing=" + mAppAnimator.freezingScreen);
+                + hidden + " freezing=" + mAppAnimator.freezingScreen + " hiddenRequested="
+                + hiddenRequested);
         if (!hiddenRequested) {
             if (!mAppAnimator.freezingScreen) {
                 mAppAnimator.freezingScreen = true;
@@ -1140,10 +834,10 @@
                     mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
                 }
             }
-            final int count = windows.size();
+            final int count = mChildren.size();
             for (int i = 0; i < count; i++) {
-                final WindowState w = windows.get(i);
-                w.mAppFreezing = true;
+                final WindowState w = (WindowState) mChildren.get(i);
+                w.onStartFreezingScreen();
             }
         }
     }
@@ -1153,22 +847,11 @@
             return;
         }
         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + this + " force=" + force);
-        final int count = windows.size();
+        final int count = mChildren.size();
         boolean unfrozeWindows = false;
         for (int i = 0; i < count; i++) {
-            final WindowState w = windows.get(i);
-            if (w.mAppFreezing) {
-                w.mAppFreezing = false;
-                if (w.mHasSurface && !w.mOrientationChanging
-                        && mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
-                    if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + w);
-                    w.mOrientationChanging = true;
-                    mService.mWindowPlacerLocked.mOrientationChangeComplete = false;
-                }
-                w.mLastFreezeDuration = 0;
-                unfrozeWindows = true;
-                w.setDisplayLayoutNeeded();
-            }
+            final WindowState w = (WindowState) mChildren.get(i);
+            unfrozeWindows |= w.onStopFreezingScreen();
         }
         if (force || unfrozeWindows) {
             if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
@@ -1283,17 +966,17 @@
         return false;
     }
 
-    int getWindowsCount() {
-        return windows.size();
+    boolean isLastWindow(WindowState win) {
+        return mChildren.size() == 1 && mChildren.get(0) == win;
     }
 
     void setAllAppWinAnimators() {
         final ArrayList<WindowStateAnimator> allAppWinAnimators = mAppAnimator.mAllAppWinAnimators;
         allAppWinAnimators.clear();
 
-        final int windowsCount = windows.size();
+        final int windowsCount = mChildren.size();
         for (int j = 0; j < windowsCount; j++) {
-            allAppWinAnimators.add(windows.get(j).mWinAnimator);
+            ((WindowState) mChildren.get(j)).addWinAnimatorToList(allAppWinAnimators);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 0a60608..990405a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -36,6 +36,7 @@
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.animation.Animation;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -623,7 +624,7 @@
      */
     TaskStack getDockedStackLocked() {
         final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
-        return (stack != null && stack.isVisibleLocked()) ? stack : null;
+        return (stack != null && stack.isVisible()) ? stack : null;
     }
 
     /**
@@ -632,7 +633,7 @@
      */
     TaskStack getDockedStackVisibleForUserLocked() {
         final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
-        return (stack != null && stack.isVisibleForUserLocked()) ? stack : null;
+        return (stack != null && stack.isVisible(true /* ignoreKeyguard */)) ? stack : null;
     }
 
     /**
@@ -669,4 +670,13 @@
 
         return touchedWin;
     }
+
+    /**
+     * See {@link WindowManagerService#overridePlayingAppAnimationsLw}.
+     */
+    void overridePlayingAppAnimationsLw(Animation a) {
+        for (int i = mStacks.size() - 1; i >= 0; i--) {
+            mStacks.get(i).overridePlayingAppAnimations(a);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 641bae2..de8e5ac 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -38,6 +38,7 @@
 import android.graphics.Rect;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.util.ArraySet;
 import android.util.Slog;
 import android.view.DisplayInfo;
 import android.view.IDockedStackListener;
@@ -492,8 +493,31 @@
         checkMinimizeChanged(false /* animate */);
     }
 
-    void notifyAppTransitionStarting() {
+    void notifyAppTransitionStarting(ArraySet<AppWindowToken> openingApps) {
+        final boolean wasMinimized = mMinimizedDock;
         checkMinimizeChanged(true /* animate */);
+
+        // We were minimized, and now we are still minimized, but somebody is trying to launch an
+        // app in docked stack, better show recent apps so we actually get unminimized! This catches
+        // any case that was missed in ActivityStarter.postStartActivityUncheckedProcessing because
+        // we couldn't retrace the launch of the app in the docked stack to the launch from
+        // homescreen.
+        if (wasMinimized && mMinimizedDock && containsAppInDockedStack(openingApps)) {
+            mService.showRecentApps(true /* fromHome */);
+        }
+    }
+
+    /**
+     * @return true if {@param apps} contains an activity in the docked stack, false otherwise.
+     */
+    private boolean containsAppInDockedStack(ArraySet<AppWindowToken> apps) {
+        for (int i = apps.size() - 1; i >= 0; i--) {
+            final AppWindowToken token = apps.valueAt(i);
+            if (token.mTask != null && token.mTask.mStack.mStackId == DOCKED_STACK_ID) {
+                return true;
+            }
+        }
+        return false;
     }
 
     boolean isMinimizedDock() {
@@ -517,7 +541,7 @@
         final ArrayList<Task> homeStackTasks = homeStack.getTasks();
         final Task topHomeStackTask = homeStackTasks.get(homeStackTasks.size() - 1);
         final boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
-        final boolean homeBehind = (fullscreenStack != null && fullscreenStack.isVisibleLocked())
+        final boolean homeBehind = (fullscreenStack != null && fullscreenStack.isVisible())
                 || (homeStackTasks.size() > 1 && topHomeStackTask != homeTask);
         // If the home task is an on-top launcher, we don't want to minimize the docked stack.
         // Instead we want everything underneath that was visible to remain visible.
@@ -615,7 +639,7 @@
         final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
         for (int i = stacks.size() - 1; i >= 0; --i) {
             final TaskStack stack = stacks.get(i);
-            if (stack.isVisibleLocked() && stack.isAdjustedForIme()) {
+            if (stack.isVisible() && stack.isAdjustedForIme()) {
                 stack.beginImeAdjustAnimation();
             }
         }
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index cb99461..e9ce0ea 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -202,7 +202,7 @@
 
     @Override
     public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) {
-        mService.setReplacingWindows(appToken, childrenOnly);
+        mService.setWillReplaceWindows(appToken, childrenOnly);
     }
 
     public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 048d980..4241b32 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -17,18 +17,14 @@
 package com.android.server.wm;
 
 import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.H.RESIZE_TASK;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 
 import android.app.ActivityManager.StackId;
 import android.content.pm.ActivityInfo;
@@ -38,12 +34,12 @@
 import android.util.Slog;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.animation.Animation;
 
 import android.view.SurfaceControl;
 import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
-import java.util.ArrayList;
 
 class Task implements DimLayer.DimLayerUser {
     static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM;
@@ -308,9 +304,9 @@
             return false;
         }
         if ((boundsChanged & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
-            resizeWindows();
+            onResize();
         } else {
-            moveWindows();
+            onMovedByResize();
         }
         return true;
     }
@@ -473,14 +469,14 @@
         }
     }
 
-    void resetDragResizingChangeReported() {
+    private void resetDragResizingChangeReported() {
         for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
             mAppTokens.get(activityNdx).resetDragResizingChangeReported();
         }
     }
 
     boolean isDragResizing() {
-        return mDragResizing || (mStack != null && mStack.isDragResizing());
+        return mDragResizing;
     }
 
     int getDragResizeMode() {
@@ -497,10 +493,12 @@
         }
     }
 
-    void detachDisplay() {
+    boolean detachFromDisplay() {
+        boolean didSomething = false;
         for (int i = mAppTokens.size() - 1; i >= 0; --i) {
-            mAppTokens.get(i).detachDisplay();
+            didSomething |= mAppTokens.get(i).detachFromDisplay();
         }
+        return didSomething;
     }
 
     void updateDisplayInfo(final DisplayContent displayContent) {
@@ -538,15 +536,15 @@
         }
     }
 
-    void resizeWindows() {
+    private void onResize() {
         for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
-            mAppTokens.get(activityNdx).resizeWindows();
+            mAppTokens.get(activityNdx).onResize();
         }
     }
 
-    void moveWindows() {
+    private void onMovedByResize() {
         for (int i = mAppTokens.size() - 1; i >= 0; --i) {
-            mAppTokens.get(i).moveWindows();
+            mAppTokens.get(i).onMovedByResize();
         }
     }
 
@@ -573,16 +571,6 @@
         return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showForAllUsers;
     }
 
-    boolean isVisibleForUser() {
-        for (int i = mAppTokens.size() - 1; i >= 0; i--) {
-            final AppWindowToken appToken = mAppTokens.get(i);
-            if (appToken.isVisibleForUser()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     boolean isVisible() {
         for (int i = mAppTokens.size() - 1; i >= 0; i--) {
             final AppWindowToken appToken = mAppTokens.get(i);
@@ -625,10 +613,6 @@
         return null;
     }
 
-    AppWindowToken getTopAppToken() {
-        return mAppTokens.size() > 0 ? mAppTokens.get(mAppTokens.size() - 1) : null;
-    }
-
     @Override
     public boolean dimFullscreen() {
         return isHomeTask() || isFullscreen();
@@ -649,6 +633,15 @@
         return mStack.getDisplayContent().getDisplayInfo();
     }
 
+    /**
+     * See {@link WindowManagerService#overridePlayingAppAnimationsLw}
+     */
+    void overridePlayingAppAnimations(Animation a) {
+        for (int i = mAppTokens.size() - 1; i >= 0; i--) {
+            mAppTokens.get(i).overridePlayingAppAnimations(a);
+        }
+    }
+
     void forceWindowsScaleable(boolean force) {
         SurfaceControl.openTransaction();
         try {
diff --git a/services/core/java/com/android/server/wm/TaskGroup.java b/services/core/java/com/android/server/wm/TaskGroup.java
deleted file mode 100644
index 1f1dd58..0000000
--- a/services/core/java/com/android/server/wm/TaskGroup.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import android.view.IApplicationToken;
-
-import java.util.ArrayList;
-
-public class TaskGroup {
-    public int taskId = -1;
-    public ArrayList<IApplicationToken> tokens = new ArrayList<IApplicationToken>();
-
-    @Override
-    public String toString() {
-        return "id=" + taskId + " tokens=" + tokens;
-    }
-}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index d2ec792..21fc08b 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -44,6 +44,7 @@
 import android.view.DisplayInfo;
 import android.view.Surface;
 import android.view.SurfaceControl;
+import android.view.animation.Animation;
 
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
@@ -112,9 +113,6 @@
     /** Detach this stack from its display when animation completes. */
     boolean mDeferDetach;
 
-    // Whether the stack and all its tasks is currently being drag-resized
-    private boolean mDragResizing;
-
     private final Rect mTmpAdjustedBounds = new Rect();
     private boolean mAdjustedForIme;
     private boolean mImeGoingAway;
@@ -380,23 +378,21 @@
             return false;
         }
 
-        final int oldDockSide = mStackId == DOCKED_STACK_ID ? getDockSide() : DOCKED_INVALID;
         mTmpRect2.set(mBounds);
         mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
         if (mStackId == DOCKED_STACK_ID) {
             repositionDockedStackAfterRotation(mTmpRect2);
             snapDockedStackAfterRotation(mTmpRect2);
             final int newDockSide = getDockSide(mTmpRect2);
-            if (oldDockSide != newDockSide) {
-                // Update the dock create mode and clear the dock create bounds, these
-                // might change after a rotation and the original values will be invalid.
-                mService.setDockedStackCreateStateLocked(
-                        (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
-                        ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
-                        : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT,
-                        null);
-                mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
-            }
+
+            // Update the dock create mode and clear the dock create bounds, these
+            // might change after a rotation and the original values will be invalid.
+            mService.setDockedStackCreateStateLocked(
+                    (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
+                    ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
+                    : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT,
+                    null);
+            mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
         }
 
         mBoundsAfterRotation.set(mTmpRect2);
@@ -657,7 +653,7 @@
             throw new IllegalStateException(
                     "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
         }
-        if (!ignoreVisibility && !dockedStack.isVisibleLocked()) {
+        if (!ignoreVisibility && !dockedStack.isVisible()) {
             // The docked stack is being dismissed, but we caught before it finished being
             // dismissed. In that case we want to treat it as if it is not occupying any space and
             // let others occupy the whole display.
@@ -763,14 +759,16 @@
                 1 /*allowResizeInDockedMode*/, bounds).sendToTarget();
     }
 
-    void detachDisplay() {
+    boolean detachFromDisplay() {
         EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
 
+        boolean didSomething = false;
         for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
-            mTasks.get(taskNdx).detachDisplay();
+            didSomething |= mTasks.get(taskNdx).detachFromDisplay();
         }
 
         close();
+        return didSomething;
     }
 
     void resetAnimationBackgroundAnimator() {
@@ -847,7 +845,7 @@
             mAdjustImeAmount = adjustAmount;
             mAdjustDividerAmount = adjustDividerAmount;
             updateAdjustedBounds();
-            return isVisibleForUserLocked();
+            return isVisible(true /* ignoreKeyguard */);
         } else {
             return false;
         }
@@ -883,7 +881,7 @@
         if (minimizeAmount != mMinimizeAmount) {
             mMinimizeAmount = minimizeAmount;
             updateAdjustedBounds();
-            return isVisibleForUserLocked();
+            return isVisible(true /* ignoreKeyguard */);
         } else {
             return false;
         }
@@ -900,7 +898,7 @@
     void beginImeAdjustAnimation() {
         for (int j = mTasks.size() - 1; j >= 0; j--) {
             final Task task = mTasks.get(j);
-            if (task.isVisibleForUser()) {
+            if (task.isVisible()) {
                 task.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
                 task.setWaitingForDrawnIfResizingChanged();
             }
@@ -1189,10 +1187,14 @@
         }
     }
 
-    boolean isVisibleLocked() {
+    boolean isVisible() {
+        return isVisible(false /* ignoreKeyguard */);
+    }
+
+    boolean isVisible(boolean ignoreKeyguard) {
         final boolean keyguardOn = mService.mPolicy.isKeyguardShowingOrOccluded()
                 && !mService.mAnimator.mKeyguardGoingAway;
-        if (keyguardOn && !StackId.isAllowedOverLockscreen(mStackId)) {
+        if (!ignoreKeyguard && keyguardOn && !StackId.isAllowedOverLockscreen(mStackId)) {
             // The keyguard is showing and the stack shouldn't show on top of the keyguard.
             return false;
         }
@@ -1209,34 +1211,6 @@
         return false;
     }
 
-    /**
-     * @return true if a the stack is visible for the current in user, ignoring any other visibility
-     *         aspects, and false otherwise
-     */
-    boolean isVisibleForUserLocked() {
-        for (int i = mTasks.size() - 1; i >= 0; i--) {
-            final Task task = mTasks.get(i);
-            if (task.isVisibleForUser()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    boolean isDragResizing() {
-        return mDragResizing;
-    }
-
-    void setDragResizingLocked(boolean resizing) {
-        if (mDragResizing == resizing) {
-            return;
-        }
-        mDragResizing = resizing;
-        for (int i = mTasks.size() - 1; i >= 0 ; i--) {
-            mTasks.get(i).resetDragResizingChangeReported();
-        }
-    }
-
     @Override  // AnimatesBounds
     public boolean setSize(Rect bounds) {
         synchronized (mService.mWindowMap) {
@@ -1317,4 +1291,13 @@
     public boolean getBoundsAnimating() {
         return mBoundsAnimating;
     }
+
+    /**
+     * See {@link WindowManagerService#overridePlayingAppAnimationsLw}
+     */
+    void overridePlayingAppAnimations(Animation a) {
+        for (int i = mTasks.size() - 1; i >= 0; --i) {
+            mTasks.get(i).overridePlayingAppAnimations(a);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 34fa1b0..5d2a52a 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -234,14 +234,12 @@
         boolean allowWhenLocked = false;
         // Show IME over the keyguard if the target allows it
         allowWhenLocked |= (win.mIsImWindow || imeTarget == win) && showImeOverKeyguard;
-        // Show SHOW_WHEN_LOCKED windows that turn on the screen
-        allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.mTurnOnScreen;
+        // Show SHOW_WHEN_LOCKED windows
+        allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0;
 
         if (appShowWhenLocked != null) {
             allowWhenLocked |= appShowWhenLocked == win.mAppToken
-                    // Show all SHOW_WHEN_LOCKED windows if some apps are shown over lockscreen
-                    || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
-                    // Show error dialogs over apps that dismiss keyguard.
+                    // Show error dialogs over apps that are shown on lockscreen
                     || (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 8cf89ec..fd6994c 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -91,4 +91,87 @@
         }
         return false;
     }
+
+    void setWaitingForDrawnIfResizingChanged() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = mChildren.get(i);
+            wc.setWaitingForDrawnIfResizingChanged();
+        }
+    }
+
+    void onResize() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = mChildren.get(i);
+            wc.onResize();
+        }
+    }
+
+    void onMovedByResize() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = mChildren.get(i);
+            wc.onMovedByResize();
+        }
+    }
+
+    void resetDragResizingChangeReported() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = mChildren.get(i);
+            wc.resetDragResizingChangeReported();
+        }
+    }
+
+    boolean detachFromDisplay() {
+        boolean didSomething = false;
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = mChildren.get(i);
+            didSomething |= wc.detachFromDisplay();
+        }
+        return didSomething;
+    }
+
+    void forceWindowsScaleableInTransaction(boolean force) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = mChildren.get(i);
+            wc.forceWindowsScaleableInTransaction(force);
+        }
+    }
+
+    boolean isAnimating() {
+        for (int j = mChildren.size() - 1; j >= 0; j--) {
+            final WindowContainer wc = mChildren.get(j);
+            if (wc.isAnimating()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void sendAppVisibilityToClients() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = mChildren.get(i);
+            wc.sendAppVisibilityToClients();
+        }
+    }
+
+    void setVisibleBeforeClientHidden() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = mChildren.get(i);
+            wc.setVisibleBeforeClientHidden();
+        }
+    }
+
+    boolean isVisible() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowContainer wc = mChildren.get(i);
+            if (wc.isVisible()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** Returns the top child container or this container if there are no children. */
+    WindowContainer getTop() {
+        return mChildren.isEmpty() ? this : mChildren.peekLast();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8389a86..856e101 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -247,6 +247,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
 
 /** {@hide} */
 public class WindowManagerService extends IWindowManager.Stub
@@ -430,7 +431,7 @@
      * List of app window tokens that are waiting for replacing windows. If the
      * replacement doesn't come in time the stale windows needs to be disposed of.
      */
-    final ArrayList<AppWindowToken> mReplacingWindowTimeouts = new ArrayList<>();
+    final ArrayList<AppWindowToken> mWindowReplacementTimeouts = new ArrayList<>();
 
     /**
      * The input consumer added to the window manager which consumes input events to windows below
@@ -2637,74 +2638,6 @@
         return atoken.mAppAnimator.animation != null;
     }
 
-    // -------------------------------------------------------------
-    // Application Window Tokens
-    // -------------------------------------------------------------
-
-    public void validateAppTokens(int stackId, List<TaskGroup> tasks) {
-        synchronized (mWindowMap) {
-            int t = tasks.size() - 1;
-            if (t < 0) {
-                Slog.w(TAG_WM, "validateAppTokens: empty task list");
-                return;
-            }
-
-            TaskGroup task = tasks.get(0);
-            int taskId = task.taskId;
-            Task targetTask = mTaskIdToTask.get(taskId);
-            DisplayContent displayContent = targetTask.getDisplayContent();
-            if (displayContent == null) {
-                Slog.w(TAG_WM, "validateAppTokens: no Display for taskId=" + taskId);
-                return;
-            }
-
-            final ArrayList<Task> localTasks = mStackIdToStack.get(stackId).getTasks();
-            int taskNdx;
-            for (taskNdx = localTasks.size() - 1; taskNdx >= 0 && t >= 0; --taskNdx, --t) {
-                AppTokenList localTokens = localTasks.get(taskNdx).mAppTokens;
-                task = tasks.get(t);
-                List<IApplicationToken> tokens = task.tokens;
-
-                DisplayContent lastDisplayContent = displayContent;
-                displayContent = mTaskIdToTask.get(taskId).getDisplayContent();
-                if (displayContent != lastDisplayContent) {
-                    Slog.w(TAG_WM, "validateAppTokens: displayContent changed in TaskGroup list!");
-                    return;
-                }
-
-                int tokenNdx;
-                int v;
-                for (tokenNdx = localTokens.size() - 1, v = task.tokens.size() - 1;
-                        tokenNdx >= 0 && v >= 0; ) {
-                    final AppWindowToken atoken = localTokens.get(tokenNdx);
-                    if (atoken.removed) {
-                        --tokenNdx;
-                        continue;
-                    }
-                    if (tokens.get(v) != atoken.token) {
-                        break;
-                    }
-                    --tokenNdx;
-                    v--;
-                }
-
-                if (tokenNdx >= 0 || v >= 0) {
-                    break;
-                }
-            }
-
-            if (taskNdx >= 0 || t >= 0) {
-                Slog.w(TAG_WM, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
-                Slog.w(TAG_WM, "validateAppTokens: Mismatch! WindowManager=" + localTasks);
-                Slog.w(TAG_WM, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
-            }
-        }
-    }
-
-    public void validateStackOrder(Integer[] remoteStackIds) {
-        // TODO:
-    }
-
     private boolean checkCallingPermission(String permission, String func) {
         // Quick check: if the calling permission is me, it's all okay.
         if (Binder.getCallingPid() == Process.myPid()) {
@@ -3645,7 +3578,7 @@
                 // If the app is dead while it was visible, we kept its dead window on screen.
                 // Now that the app is going invisible, we can remove it. It will be restarted
                 // if made visible again.
-                wtoken.removeAllDeadWindows();
+                wtoken.removeDeadWindows();
                 wtoken.setVisibleBeforeClientHidden();
             } else if (visible) {
                 if (!mAppTransition.isTransitionSet() && mAppTransition.isReady()) {
@@ -4010,7 +3943,7 @@
 
     boolean isStackVisibleLocked(int stackId) {
         final TaskStack stack = mStackIdToStack.get(stackId);
-        return (stack != null && stack.isVisibleLocked());
+        return (stack != null && stack.isVisible());
     }
 
     public void setDockedStackCreateState(int mode, Rect bounds) {
@@ -4080,7 +4013,9 @@
 
     void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
         displayContent.detachStack(stack);
-        stack.detachDisplay();
+        if (stack.detachFromDisplay()) {
+            mWindowPlacerLocked.requestTraversal();
+        }
         if (stack.mStackId == DOCKED_STACK_ID) {
             getDefaultDisplayContentLocked().mDividerControllerLocked
                     .notifyDockedStackExistsChanged(false);
@@ -4201,6 +4136,11 @@
         }
     }
 
+    @Override
+    public void overridePlayingAppAnimationsLw(Animation a) {
+        getDefaultDisplayContentLocked().overridePlayingAppAnimationsLw(a);
+    }
+
     /**
      * Re-sizes a stack and its containing tasks.
      * @param stackId Id of stack to resize.
@@ -4219,7 +4159,7 @@
                         + " not found.");
             }
             if (stack.setBounds(bounds, configs, taskBounds, taskTempInsetBounds)
-                    && stack.isVisibleLocked()) {
+                    && stack.isVisible()) {
                 stack.getDisplayContent().layoutNeeded = true;
                 mWindowPlacerLocked.performSurfacePlacement();
             }
@@ -6786,7 +6726,7 @@
             for (int i = stacks.size() - 1; i >= 0; --i) {
                 final TaskStack stack = stacks.get(i);
                 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
-                if (stack.isVisibleLocked() && (imeOnBottom || isDockedOnBottom)) {
+                if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) {
                     stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
                 } else {
                     stack.resetAdjustedForIme(false);
@@ -7742,11 +7682,11 @@
                 break;
                 case WINDOW_REPLACEMENT_TIMEOUT: {
                     synchronized (mWindowMap) {
-                        for (int i = mReplacingWindowTimeouts.size() - 1; i >= 0; i--) {
-                            final AppWindowToken token = mReplacingWindowTimeouts.get(i);
-                            token.clearTimedoutReplacesLocked();
+                        for (int i = mWindowReplacementTimeouts.size() - 1; i >= 0; i--) {
+                            final AppWindowToken token = mWindowReplacementTimeouts.get(i);
+                            token.onWindowReplacementTimeout();
                         }
-                        mReplacingWindowTimeouts.clear();
+                        mWindowReplacementTimeouts.clear();
                     }
                 }
                 case NOTIFY_APP_TRANSITION_STARTING: {
@@ -7871,7 +7811,7 @@
                             && 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.getFirstWindow(imFocus);
+                        final WindowState w = imFocus.mAppToken.getFirstNonStartingWindow();
                         if (w != null) {
                             if (DEBUG_INPUT_METHOD) Slog.i(TAG_WM,
                                     "Switching to real app window: " + w);
@@ -8513,7 +8453,7 @@
                 // If it's a dead window left on screen, and the configuration changed,
                 // there is nothing we can do about it. Remove the window now.
                 if (w.mAppToken != null && w.mAppDied) {
-                    w.mAppToken.removeAllDeadWindows();
+                    w.mAppToken.removeDeadWindows();
                     return;
                 }
 
@@ -10010,16 +9950,15 @@
      * a window.
      * @param token Application token for which the activity will be relaunched.
      */
-    public void setReplacingWindow(IBinder token, boolean animate) {
-        AppWindowToken appWindowToken = null;
+    public void setWillReplaceWindow(IBinder token, boolean animate) {
         synchronized (mWindowMap) {
-            appWindowToken = findAppWindowToken(token);
+            final AppWindowToken appWindowToken = findAppWindowToken(token);
             if (appWindowToken == null || !appWindowToken.isVisible()) {
                 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
                         + token);
                 return;
             }
-            appWindowToken.setReplacingWindows(animate);
+            appWindowToken.setWillReplaceWindows(animate);
         }
     }
 
@@ -10033,10 +9972,11 @@
      *                     reused rather than replaced).
      *
      */
-    public void setReplacingWindows(IBinder token, boolean childrenOnly) {
-        AppWindowToken appWindowToken = null;
+    // TODO: The s at the end of the method name is the only difference with the name of the method
+    // above. We should combine them or find better names.
+    public void setWillReplaceWindows(IBinder token, boolean childrenOnly) {
         synchronized (mWindowMap) {
-            appWindowToken = findAppWindowToken(token);
+            final AppWindowToken appWindowToken = findAppWindowToken(token);
             if (appWindowToken == null || !appWindowToken.isVisible()) {
                 Slog.w(TAG_WM, "Attempted to set replacing window on non-existing app token "
                         + token);
@@ -10044,12 +9984,12 @@
             }
 
             if (childrenOnly) {
-                appWindowToken.setReplacingChildren();
+                appWindowToken.setWillReplaceChildWindows();
             } else {
-                appWindowToken.setReplacingWindows(false /* animate */);
+                appWindowToken.setWillReplaceWindows(false /* animate */);
             }
 
-            scheduleClearReplacingWindowIfNeeded(token, true /* replacing */);
+            scheduleClearWillReplaceWindows(token, true /* replacing */);
         }
     }
 
@@ -10062,26 +10002,25 @@
      * @param token Application token for the activity whose window might be replaced.
      * @param replacing Whether the window is being replaced or not.
      */
-    public void scheduleClearReplacingWindowIfNeeded(IBinder token, boolean replacing) {
-        AppWindowToken appWindowToken = null;
+    public void scheduleClearWillReplaceWindows(IBinder token, boolean replacing) {
         synchronized (mWindowMap) {
-            appWindowToken = findAppWindowToken(token);
+            final AppWindowToken appWindowToken = findAppWindowToken(token);
             if (appWindowToken == null) {
                 Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token "
                         + token);
                 return;
             }
             if (replacing) {
-                scheduleReplacingWindowTimeouts(appWindowToken);
+                scheduleWindowReplacementTimeouts(appWindowToken);
             } else {
-                appWindowToken.resetReplacingWindows();
+                appWindowToken.clearWillReplaceWindows();
             }
         }
     }
 
-    void scheduleReplacingWindowTimeouts(AppWindowToken appWindowToken) {
-        if (!mReplacingWindowTimeouts.contains(appWindowToken)) {
-            mReplacingWindowTimeouts.add(appWindowToken);
+    void scheduleWindowReplacementTimeouts(AppWindowToken appWindowToken) {
+        if (!mWindowReplacementTimeouts.contains(appWindowToken)) {
+            mWindowReplacementTimeouts.add(appWindowToken);
         }
         mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
         mH.sendEmptyMessageDelayed(
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index cb8660b..2c359fc 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -99,6 +99,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static android.view.WindowManagerPolicy.TRANSIT_ENTER;
 import static android.view.WindowManagerPolicy.TRANSIT_EXIT;
 import static android.view.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
@@ -117,6 +118,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
 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.TAG_WITH_CLASS_NAME;
@@ -126,6 +128,7 @@
 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 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.localLOGV;
 import static com.android.server.wm.WindowStateAnimator.COMMIT_DRAW_PENDING;
 import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
@@ -486,7 +489,7 @@
     boolean mAnimateReplacingWindow = false;
     // If not null, the window that will be used to replace the old one. This is being set when
     // the window is added and unset when this window reports its first draw.
-    WindowState mReplacingWindow = null;
+    WindowState mReplacementWindow = null;
     // For the new window in the replacement transition, if we have
     // requested to replace without animation, then we should
     // make sure we also don't apply an enter animation for
@@ -531,6 +534,8 @@
      */
     boolean mSeamlesslyRotated = false;
 
+    private static final Region sEmptyRegion = new Region();
+
     /**
      * Compares to window sub-layers and returns -1 if the first is lesser than the second in terms
      * of z-order and 1 otherwise.
@@ -599,7 +604,7 @@
         }
         mDeathRecipient = deathRecipient;
 
-        if ((mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW)) {
+        if (mAttrs.type >= FIRST_SUB_WINDOW && mAttrs.type <= LAST_SUB_WINDOW) {
             // The multiplier here is to reserve space for multiple
             // windows in the same type layer.
             mBaseLayer = mPolicy.windowTypeToLayerLw(parentWindow.mAttrs.type)
@@ -1165,6 +1170,21 @@
         }
     }
 
+    // TODO: Sigh...another is visible method...tried to consolidate with other isVisible methods
+    // below, but failed. Need to figure-out a good way to handle this long term...
+    @Override
+    boolean isVisible() {
+        // If we're animating with a saved surface, we're already visible.
+        // Return true so that the alpha doesn't get cleared.
+        if (!mAppFreezing && isDrawnLw()
+                && (mViewVisibility == View.VISIBLE || isAnimatingWithSavedSurface()
+                || (mWinAnimator.isAnimationSet() && !mService.mAppTransition.isTransitionSet()))) {
+            return true;
+        }
+
+        return super.isVisible();
+    }
+
     /**
      * Does the minimal check for visibility. Callers generally want to use one of the public
      * methods as they perform additional checks on the app token.
@@ -1402,6 +1422,126 @@
                 && (mAppToken == null || mAppToken.mAppAnimator.animation == null);
     }
 
+    @Override
+    void onMovedByResize() {
+        if (DEBUG_RESIZE) Slog.d(TAG, "onMovedByResize: Moving " + this);
+        mMovedByResize = true;
+        super.onMovedByResize();
+    }
+
+    boolean onAppVisibilityChanged(boolean visible, boolean runningAppAnimation) {
+        boolean changed = false;
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            changed |= c.onAppVisibilityChanged(visible, runningAppAnimation);
+        }
+
+        if (mAttrs.type == TYPE_APPLICATION_STARTING) {
+            // Starting window that's exiting will be removed when the animation finishes.
+            // Mark all relevant flags for that onExitAnimationDone will proceed all the way
+            // to actually remove it.
+            if (!visible && isVisibleNow() && mAppToken.mAppAnimator.isAnimating()) {
+                mAnimatingExit = true;
+                mRemoveOnExit = true;
+                mWindowRemovalAllowed = true;
+            }
+            return changed;
+        }
+
+        if (visible != isVisibleNow()) {
+            if (!runningAppAnimation) {
+                final AccessibilityController accessibilityController =
+                        mService.mAccessibilityController;
+                final int winTransit = visible ? TRANSIT_ENTER : TRANSIT_EXIT;
+                mWinAnimator.applyAnimationLocked(winTransit, visible);
+                //TODO (multidisplay): Magnification is supported only for the default
+                if (accessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
+                    accessibilityController.onWindowTransitionLocked(this, winTransit);
+                }
+            }
+            changed = true;
+            setDisplayLayoutNeeded();
+        }
+
+        return changed;
+    }
+
+    boolean onSetAppExiting() {
+        final DisplayContent displayContent = getDisplayContent();
+        boolean changed = false;
+
+        if (isVisibleNow()) {
+            mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
+            //TODO (multidisplay): Magnification is supported only for the default
+            if (mService.mAccessibilityController != null && isDefaultDisplay()) {
+                mService.mAccessibilityController.onWindowTransitionLocked(this, TRANSIT_EXIT);
+            }
+            changed = true;
+            if (displayContent != null) {
+                displayContent.layoutNeeded = true;
+            }
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            changed |= c.onSetAppExiting();
+        }
+
+        return changed;
+    }
+
+    @Override
+    void onResize() {
+        // Some windows won't go through the resizing process, if they don't have a surface, so
+        // destroy all saved surfaces here.
+        destroySavedSurface();
+
+        final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
+        if (mHasSurface && !resizingWindows.contains(this)) {
+            if (DEBUG_RESIZE) Slog.d(TAG, "onResize: Resizing " + this);
+            resizingWindows.add(this);
+
+            // If we are not drag resizing, force recreating of a new surface so updating
+            // the content and positioning that surface will be in sync.
+            //
+            // As we use this flag as a hint to freeze surface boundary updates, we'd like to only
+            // apply this to TYPE_BASE_APPLICATION, windows of TYPE_APPLICATION like dialogs, could
+            // appear to not be drag resizing while they resize, but we'd still like to manipulate
+            // their frame to update crop, etc...
+            //
+            // Anyway we don't need to synchronize position and content updates for these
+            // windows since they aren't at the base layer and could be moved around anyway.
+            if (!computeDragResizing() && mAttrs.type == TYPE_BASE_APPLICATION &&
+                    !getTask().mStack.getBoundsAnimating() && !isGoneForLayoutLw() &&
+                    !getTask().inPinnedWorkspace()) {
+                setResizedWhileNotDragResizing(true);
+            }
+        }
+        if (isGoneForLayoutLw()) {
+            mResizedWhileGone = true;
+        }
+
+        super.onResize();
+    }
+
+    void onUnfreezeBounds() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.onUnfreezeBounds();
+        }
+
+        if (!mHasSurface) {
+            return;
+        }
+
+        mLayoutNeeded = true;
+        setDisplayLayoutNeeded();
+        if (!mService.mResizingWindows.contains(this)) {
+            mService.mResizingWindows.add(this);
+        }
+    }
+
     /**
      * Return whether this window has moved. (Only makes
      * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
@@ -1451,6 +1591,32 @@
                 && mAppToken.mTask.mStack.isAdjustedForMinimizedDock();
     }
 
+    void onWindowReplacementTimeout() {
+        if (mWillReplaceWindow) {
+            // Since the window already timed out, remove it immediately now.
+            // Use WindowState#remove() instead of WindowState#removeIfPossible(), as the latter
+            // delays removal on certain conditions, which will leave the stale window in the
+            // stack and marked mWillReplaceWindow=false, so the window will never be removed.
+            //
+            // Also removes child windows.
+            remove();
+        } else {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                final WindowState c = (WindowState) mChildren.get(i);
+                c.onWindowReplacementTimeout();
+            }
+        }
+    }
+
+    @Override
+    void forceWindowsScaleableInTransaction(boolean force) {
+        if (mWinAnimator != null && mWinAnimator.hasSurface()) {
+            mWinAnimator.mSurfaceController.forceScaleableInTransaction(force);
+        }
+
+        super.forceWindowsScaleableInTransaction(force);
+    }
+
     @Override
     void remove() {
         super.remove();
@@ -1463,6 +1629,11 @@
 
         mRemoved = true;
 
+        mWillReplaceWindow = false;
+        if (mReplacementWindow != null) {
+            mReplacementWindow.mSkipEnterAnimationForSeamlessReplacement = false;
+        }
+
         if (mService.mInputMethodTarget == this) {
             mService.moveInputMethodWindowsIfNeededLocked(false);
         }
@@ -1490,6 +1661,10 @@
     }
 
     void removeIfPossible() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.removeIfPossible(false /*keepVisibleDeadWindow*/);
+        }
         removeIfPossible(false /*keepVisibleDeadWindow*/);
     }
 
@@ -1598,7 +1773,7 @@
             final boolean isAnimating =
                     mWinAnimator.isAnimationSet() && !mWinAnimator.isDummyAnimation();
             final boolean lastWindowIsStartingWindow = startingWindow && mAppToken != null
-                    && mAppToken.getWindowsCount() == 1;
+                    && mAppToken.isLastWindow(this);
             // We delay the removal of a window if it has a showing surface that can be used to run
             // exit animation and it is marked as exiting.
             // Also, If isn't the an animating starting window that is the last window in the app.
@@ -1628,6 +1803,15 @@
         Binder.restoreCallingIdentity(origId);
     }
 
+    @Override
+    boolean detachFromDisplay() {
+        // We are in the middle of changing the state of displays/stacks/tasks. We need
+        // to finish that, before we let layout interfere with it.
+        // Also removes child windows.
+        removeIfPossible();
+        return true;
+    }
+
     private void setupWindowForRemoveOnExit() {
         mRemoveOnExit = true;
         setDisplayLayoutNeeded();
@@ -1690,6 +1874,11 @@
      */
     void notifyMovedInStack() {
         mJustMovedInStack = true;
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.notifyMovedInStack();
+        }
     }
 
     /**
@@ -1706,6 +1895,11 @@
      */
     void resetJustMovedInStack() {
         mJustMovedInStack = false;
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.resetJustMovedInStack();
+        }
     }
 
     private final class DeadWindowEventReceiver extends InputEventReceiver {
@@ -1789,6 +1983,23 @@
         return getStack();
     }
 
+    /** Returns true if the replacement window was removed. */
+    boolean removeReplacedWindowIfNeeded(WindowState replacement) {
+        if (mWillReplaceWindow && mReplacementWindow == replacement && replacement.hasDrawnLw()) {
+            replacement.mSkipEnterAnimationForSeamlessReplacement = false;
+            removeReplacedWindow();
+            return true;
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            if (c.removeReplacedWindowIfNeeded(replacement)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     void removeReplacedWindow() {
         if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + this);
         if (isDimming()) {
@@ -1797,12 +2008,31 @@
         mWillReplaceWindow = false;
         mAnimateReplacingWindow = false;
         mReplacingRemoveRequested = false;
-        mReplacingWindow = null;
+        mReplacementWindow = null;
         if (mAnimatingExit || !mAnimateReplacingWindow) {
             remove();
         }
     }
 
+    boolean setReplacementWindowIfNeeded(WindowState replacementCandidate) {
+        boolean replacementSet = false;
+
+        if (mWillReplaceWindow && mReplacementWindow == null
+                && getWindowTag().toString().equals(replacementCandidate.getWindowTag().toString())) {
+
+            mReplacementWindow = replacementCandidate;
+            replacementCandidate.mSkipEnterAnimationForSeamlessReplacement = !mAnimateReplacingWindow;
+            replacementSet = true;
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            replacementSet |= c.setReplacementWindowIfNeeded(replacementCandidate);
+        }
+
+        return replacementSet;
+    }
+
     void setDisplayLayoutNeeded() {
         if (mDisplayContent != null) {
             mDisplayContent.layoutNeeded = true;
@@ -2058,8 +2288,7 @@
                 doAnimation = false;
             }
         }
-        boolean current = doAnimation ? mPolicyVisibilityAfterAnim
-                : mPolicyVisibility;
+        boolean current = doAnimation ? mPolicyVisibilityAfterAnim : mPolicyVisibility;
         if (!current) {
             // Already hiding.
             return false;
@@ -2070,11 +2299,9 @@
                 doAnimation = false;
             }
         }
-        if (doAnimation) {
-            mPolicyVisibilityAfterAnim = false;
-        } else {
+        mPolicyVisibilityAfterAnim = false;
+        if (!doAnimation) {
             if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
-            mPolicyVisibilityAfterAnim = false;
             mPolicyVisibility = false;
             // Window is no longer visible -- make sure if we were waiting
             // for it to be displayed before enabling the display, that
@@ -2146,24 +2373,131 @@
         return mAnimatingWithSavedSurface;
     }
 
+    @Override
+    boolean isAnimating() {
+        if (mWinAnimator.isAnimationSet() || mAnimatingExit) {
+            return true;
+        }
+        return super.isAnimating();
+    }
+
     boolean isAnimatingInvisibleWithSavedSurface() {
-        return mAnimatingWithSavedSurface
-                && (mViewVisibility != View.VISIBLE || mWindowRemovalAllowed);
+        if (mAnimatingWithSavedSurface
+                && (mViewVisibility != View.VISIBLE || mWindowRemovalAllowed)) {
+            return true;
+        }
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            if (c.isAnimatingInvisibleWithSavedSurface()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void stopUsingSavedSurface() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.stopUsingSavedSurface();
+        }
+
+        if (!isAnimatingInvisibleWithSavedSurface()) {
+            return;
+        }
+
+        if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.d(TAG, "stopUsingSavedSurface: " + this);
+        clearAnimatingWithSavedSurface();
+        mDestroying = true;
+        mWinAnimator.hide("stopUsingSavedSurface");
+        mService.mWallpaperControllerLocked.hideWallpapers(this);
+    }
+
+    void markSavedSurfaceExiting() {
+        if (isAnimatingInvisibleWithSavedSurface()) {
+            mAnimatingExit = true;
+            mWinAnimator.mAnimating = true;
+        }
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.markSavedSurfaceExiting();
+        }
+    }
+
+    void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) {
+        animators.add(mWinAnimator);
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.addWinAnimatorToList(animators);
+        }
+    }
+
+    void sendAppVisibilityToClients() {
+        super.sendAppVisibilityToClients();
+
+        final boolean clientHidden = mAppToken.clientHidden;
+        if (mAttrs.type == TYPE_APPLICATION_STARTING && clientHidden) {
+            // Don't hide the starting window.
+            return;
+        }
+
+        try {
+            if (DEBUG_VISIBILITY) Slog.v(TAG,
+                    "Setting visibility of " + this + ": " + (!clientHidden));
+            mClient.dispatchAppVisibility(!clientHidden);
+        } catch (RemoteException e) {
+        }
     }
 
     public void setVisibleBeforeClientHidden() {
         mWasVisibleBeforeClientHidden |=
                 (mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface);
+
+        super.setVisibleBeforeClientHidden();
     }
 
-    public void clearVisibleBeforeClientHidden() {
+    public void clearWasVisibleBeforeClientHidden() {
         mWasVisibleBeforeClientHidden = false;
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.clearWasVisibleBeforeClientHidden();
+        }
     }
 
     public boolean wasVisibleBeforeClientHidden() {
         return mWasVisibleBeforeClientHidden;
     }
 
+    void onStartFreezingScreen() {
+        mAppFreezing = true;
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.onStartFreezingScreen();
+        }
+    }
+
+    boolean onStopFreezingScreen() {
+        boolean unfrozeWindows = false;
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            unfrozeWindows |= c.onStopFreezingScreen();
+        }
+
+        if (!mAppFreezing) {
+            return unfrozeWindows;
+        }
+
+        if (mHasSurface && !mOrientationChanging
+                && mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
+            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + this);
+            mOrientationChanging = true;
+            mService.mWindowPlacerLocked.mOrientationChangeComplete = false;
+        }
+        mLastFreezeDuration = 0;
+        setDisplayLayoutNeeded();
+        return true;
+    }
+
     private boolean shouldSaveSurface() {
         if (mWinAnimator.mSurfaceController == null) {
             // Don't bother if the surface controller is gone for any reason.
@@ -2212,7 +2546,38 @@
         return mAppToken.shouldSaveSurface();
     }
 
-    static final Region sEmptyRegion = new Region();
+    boolean destroySurface(boolean cleanupOnResume, boolean appStopped) {
+        boolean destroyedSomething = false;
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            destroyedSomething |= c.destroySurface(cleanupOnResume, appStopped);
+        }
+
+        if (appStopped || mWindowRemovalAllowed || cleanupOnResume) {
+
+            mWinAnimator.destroyPreservedSurfaceLocked();
+
+            if (mDestroying) {
+                if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + this
+                        + " destroySurfaces: appStopped=" + appStopped
+                        + " win.mWindowRemovalAllowed=" + mWindowRemovalAllowed
+                        + " win.mRemoveOnExit=" + mRemoveOnExit);
+
+                if (!cleanupOnResume || mRemoveOnExit) {
+                    destroyOrSaveSurface();
+                }
+                if (mRemoveOnExit) {
+                    remove();
+                }
+                if (cleanupOnResume) {
+                    requestUpdateWallpaperIfNeeded();
+                }
+                mDestroying = false;
+                destroyedSomething = true;
+            }
+        }
+        return destroyedSomething;
+    }
 
     void destroyOrSaveSurface() {
         mSurfaceSaved = shouldSaveSurface();
@@ -2243,29 +2608,65 @@
     }
 
     void destroySavedSurface() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.destroySavedSurface();
+        }
+
         if (mSurfaceSaved) {
-            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
-                Slog.v(TAG, "Destroying saved surface: " + this);
-            }
+            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG, "Destroying saved surface: " + this);
             mWinAnimator.destroySurfaceLocked();
             mSurfaceSaved = false;
         }
         mWasVisibleBeforeClientHidden = false;
     }
 
-    void restoreSavedSurface() {
-        if (!mSurfaceSaved) {
-            return;
+    /** Returns -1 if there are no interesting windows or number of interesting windows not drawn.*/
+    int restoreSavedSurfaceForInterestingWindow() {
+        int interestingNotDrawn = -1;
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            final int childInterestingNotDrawn = c.restoreSavedSurfaceForInterestingWindow();
+            if (childInterestingNotDrawn != -1) {
+                if (interestingNotDrawn == -1) {
+                    interestingNotDrawn = childInterestingNotDrawn;
+                } else {
+                    interestingNotDrawn += childInterestingNotDrawn;
+                }
+            }
         }
 
-        // Sometimes we save surfaces due to layout invisible
-        // directly after rotation occurs. However this means
-        // the surface was never laid out in the new orientation.
-        // We can only restore to the last rotation we were
-        // laid out as visible in.
+        if (mAttrs.type == TYPE_APPLICATION_STARTING
+                || mAppDied || !wasVisibleBeforeClientHidden()
+                || (mAppToken.mAppAnimator.freezingScreen && mAppFreezing)) {
+            // Window isn't interesting...
+            return interestingNotDrawn;
+        }
+
+        restoreSavedSurface();
+
+        if (!isDrawnLw()) {
+            if (interestingNotDrawn == -1) {
+                interestingNotDrawn = 1;
+            } else {
+                interestingNotDrawn++;
+            }
+        }
+        return interestingNotDrawn;
+    }
+
+    /** Returns true if the saved surface was restored. */
+    boolean restoreSavedSurface() {
+        if (!mSurfaceSaved) {
+            return false;
+        }
+
+        // Sometimes we save surfaces due to layout invisible directly after rotation occurs.
+        // However this means the surface was never laid out in the new orientation.
+        // We can only restore to the last rotation we were laid out as visible in.
         if (mLastVisibleLayoutRotation != mService.mRotation) {
             destroySavedSurface();
-            return;
+            return false;
         }
         mSurfaceSaved = false;
 
@@ -2285,10 +2686,23 @@
             // or resize, mSurfaceSaved flag should have been cleared. So this is a wtf.
             Slog.wtf(TAG, "Failed to restore saved surface: surface gone! " + this);
         }
+
+        return true;
     }
 
     boolean canRestoreSurface() {
-        return mWasVisibleBeforeClientHidden && mSurfaceSaved;
+        if (mWasVisibleBeforeClientHidden && mSurfaceSaved) {
+            return true;
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            if (c.canRestoreSurface()) {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     boolean hasSavedSurface() {
@@ -2601,6 +3015,14 @@
         return mDragResizing != computeDragResizing();
     }
 
+    @Override
+    void setWaitingForDrawnIfResizingChanged() {
+        if (isDragResizeChanged()) {
+            mService.mWaitingForDrawn.add(this);
+        }
+        super.setWaitingForDrawnIfResizingChanged();
+    }
+
     /**
      * @return Whether we reported a drag resize change to the application or not already.
      */
@@ -2611,8 +3033,10 @@
     /**
      * Resets the state whether we reported a drag resize change to the app.
      */
+    @Override
     void resetDragResizingChangeReported() {
         mDragResizingChangeReported = false;
+        super.resetDragResizingChangeReported();
     }
 
     /**
@@ -3009,7 +3433,8 @@
     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.
-        return (WindowState) mChildren.peekFirst();
+        WindowContainer c = mChildren.peekFirst();
+        return c == null ? null : (WindowState)c;
     }
 
     boolean layoutInParentFrame() {
@@ -3038,7 +3463,12 @@
         return (parent == null) ? false : parent.mHidden;
     }
 
-    void setReplacing(boolean animate) {
+    void setWillReplaceWindow(boolean animate) {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.setWillReplaceWindow(animate);
+        }
+
         if ((mAttrs.privateFlags & PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH) != 0
                 || mAttrs.type == TYPE_APPLICATION_STARTING) {
             // We don't set replacing on starting windows since they are added by window manager and
@@ -3047,14 +3477,33 @@
         }
 
         mWillReplaceWindow = true;
-        mReplacingWindow = null;
+        mReplacementWindow = null;
         mAnimateReplacingWindow = animate;
     }
 
-    void resetReplacing() {
+    void clearWillReplaceWindow() {
         mWillReplaceWindow = false;
-        mReplacingWindow = null;
+        mReplacementWindow = null;
         mAnimateReplacingWindow = false;
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.clearWillReplaceWindow();
+        }
+    }
+
+    boolean waitingForReplacement() {
+        if (mWillReplaceWindow) {
+            return true;
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            if (c.waitingForReplacement()) {
+                return true;
+            }
+        }
+        return false;
     }
 
     void requestUpdateWallpaperIfNeeded() {
@@ -3063,6 +3512,11 @@
             mDisplayContent.layoutNeeded = true;
             mService.mWindowPlacerLocked.requestTraversal();
         }
+
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.requestUpdateWallpaperIfNeeded();
+        }
     }
 
     float translateToWindowX(float x) {
@@ -3085,7 +3539,7 @@
         final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
         if (dimLayerUser != null && mDisplayContent != null) {
             mDisplayContent.mDimLayerController.applyDim(dimLayerUser,
-                    mReplacingWindow.mWinAnimator,
+                    mReplacementWindow.mWinAnimator,
                     (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? true : false);
         }
     }
@@ -3103,6 +3557,30 @@
                 || mAttrs.type == TYPE_DRAWN_APPLICATION;
     }
 
+    void setWillReplaceChildWindows() {
+        if (shouldBeReplacedWithChildren()) {
+            setWillReplaceWindow(false /* animate */);
+        }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.setWillReplaceChildWindows();
+        }
+    }
+
+    WindowState getReplacingWindow() {
+        if (mAnimatingExit && mWillReplaceWindow && mAnimateReplacingWindow) {
+            return this;
+        }
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            final WindowState replacing = c.getReplacingWindow();
+            if (replacing != null) {
+                return replacing;
+            }
+        }
+        return null;
+    }
+
     public int getRotationAnimationHint() {
         if (mAppToken != null) {
             return mAppToken.mRotationAnimationHint;
@@ -3211,13 +3689,30 @@
         return windowInfo;
     }
 
-    void adjustAnimLayer(int adj) {
-        mWinAnimator.mAnimLayer = mLayer + adj;
-        if (DEBUG_LAYERS) Slog.v(TAG_WM, "win=" + this + " anim layer: " + mWinAnimator.mAnimLayer);
+    int getHighestAnimLayer() {
+        int highest = mWinAnimator.mAnimLayer;
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            final int childLayer = c.getHighestAnimLayer();
+            if (childLayer > highest) {
+                highest = childLayer;
+            }
+        }
+        return highest;
+    }
+
+    int adjustAnimLayer(int adj) {
+        int highestAnimLayer = mWinAnimator.mAnimLayer = mLayer + adj;
+        if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG_WM,
+                "adjustAnimLayer win=" + this + " anim layer: " + mWinAnimator.mAnimLayer);
         for (int i = mChildren.size() - 1; i >= 0; i--) {
             final WindowState childWindow = (WindowState) mChildren.get(i);
             childWindow.adjustAnimLayer(adj);
+            if (childWindow.mWinAnimator.mAnimLayer > highestAnimLayer) {
+                highestAnimLayer = childWindow.mWinAnimator.mAnimLayer;
+            }
         }
+        return highestAnimLayer;
     }
 
     // TODO: come-up with a better name for this method that represents what it does.
@@ -3280,6 +3775,19 @@
         return interestingPos;
     }
 
+    boolean isWindowAnimationSet() {
+        if (mWinAnimator.isWindowAnimationSet()) {
+            return true;
+        }
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            if (c.isWindowAnimationSet()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     void onExitAnimationDone() {
         if (DEBUG_ANIM) Slog.v(TAG, "onExitAnimationDone in " + this
                 + ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit
@@ -3351,11 +3859,54 @@
         mService.mWallpaperControllerLocked.hideWallpapers(this);
     }
 
+    boolean clearAnimatingFlags() {
+        boolean didSomething = false;
+        // We don't want to clear it out for windows that get replaced, because the
+        // animation depends on the flag to remove the replaced window.
+        //
+        // We also don't clear the mAnimatingExit flag for windows which have the
+        // mRemoveOnExit flag. This indicates an explicit remove request has been issued
+        // by the client. We should let animation proceed and not clear this flag or
+        // they won't eventually be removed by WindowStateAnimator#finishExit.
+        if (!mWillReplaceWindow && !mRemoveOnExit) {
+            // Clear mAnimating flag together with mAnimatingExit. When animation
+            // changes from exiting to entering, we need to clear this flag until the
+            // new animation gets applied, so that isAnimationStarting() becomes true
+            // until then.
+            // Otherwise applySurfaceChangesTransaction will fail to skip surface
+            // placement for this window during this period, one or more frame will
+            // show up with wrong position or scale.
+            if (mAnimatingExit) {
+                mAnimatingExit = false;
+                didSomething = true;
+            }
+            if (mWinAnimator.mAnimating) {
+                mWinAnimator.mAnimating = false;
+                didSomething = true;
+            }
+            if (mDestroying) {
+                mDestroying = false;
+                mService.mDestroySurface.remove(this);
+                didSomething = true;
+            }
+        }
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            didSomething |= ((WindowState) mChildren.get(i)).clearAnimatingFlags();
+        }
+
+        return didSomething;
+    }
+
     public boolean isRtl() {
         return mMergedConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
     }
 
     void hideWallpaperWindow(boolean wasDeferred, String reason) {
+        for (int j = mChildren.size() - 1; j >= 0; --j) {
+            final WindowState c = (WindowState) mChildren.get(j);
+            c.hideWallpaperWindow(wasDeferred, reason);
+        }
         if (!mWinAnimator.mLastHidden || wasDeferred) {
             mWinAnimator.hide(reason);
             dispatchWallpaperVisibility(false);
@@ -3388,6 +3939,19 @@
         }
     }
 
+    boolean hasVisibleNotDrawnWallpaper() {
+        if (mWallpaperVisible && !isDrawnLw()) {
+            return true;
+        }
+        for (int j = mChildren.size() - 1; j >= 0; --j) {
+            final WindowState c = (WindowState) mChildren.get(j);
+            if (c.hasVisibleNotDrawnWallpaper()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /** Places this window after the input window in the window list. */
     void addWindowToListAfter(WindowState pos) {
         final WindowList windows = pos.getWindowList();
@@ -3441,4 +4005,57 @@
         windows.add(i, this);
         mService.mWindowsChanged = true;
     }
+
+    void updateReportedVisibility(UpdateReportedVisibilityResults results) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState c = (WindowState) mChildren.get(i);
+            c.updateReportedVisibility(results);
+        }
+
+        if (mAppFreezing || mViewVisibility != View.VISIBLE
+                || mAttrs.type == TYPE_APPLICATION_STARTING
+                || mDestroying) {
+            return;
+        }
+        if (DEBUG_VISIBILITY) {
+            Slog.v(TAG, "Win " + this + ": isDrawn=" + isDrawnLw()
+                    + ", isAnimationSet=" + mWinAnimator.isAnimationSet());
+            if (!isDrawnLw()) {
+                Slog.v(TAG, "Not displayed: s=" + mWinAnimator.mSurfaceController
+                        + " pv=" + mPolicyVisibility
+                        + " mDrawState=" + mWinAnimator.mDrawState
+                        + " ph=" + isParentWindowHidden()
+                        + " th=" + (mAppToken != null ? mAppToken.hiddenRequested : false)
+                        + " a=" + mWinAnimator.mAnimating);
+            }
+        }
+
+        results.numInteresting++;
+        if (isDrawnLw()) {
+            results.numDrawn++;
+            if (!mWinAnimator.isAnimationSet()) {
+                results.numVisible++;
+            }
+            results.nowGone = false;
+        } else if (mWinAnimator.isAnimationSet()) {
+            results.nowGone = false;
+        }
+    }
+
+    // TODO: Hack to work around the number of states AppWindowToken needs to access without having
+    // access to its windows children. Need to investigate re-writing
+    // {@link AppWindowToken#updateReportedVisibilityLocked} so this can be removed.
+    static final class UpdateReportedVisibilityResults {
+        int numInteresting;
+        int numVisible;
+        int numDrawn;
+        boolean nowGone = true;
+
+        void reset() {
+            numInteresting = 0;
+            numVisible = 0;
+            numDrawn = 0;
+            nowGone = true;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index dfee8de..b9956c8 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -597,10 +597,9 @@
 
     WindowSurfaceController createSurfaceLocked() {
         final WindowState w = mWin;
-        if (w.hasSavedSurface()) {
+        if (w.restoreSavedSurface()) {
             if (DEBUG_ANIM) Slog.i(TAG,
                     "createSurface: " + this + ": called when we had a saved surface");
-            w.restoreSavedSurface();
             return mSurfaceController;
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index c77e572..f5ed9d1 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -153,9 +153,9 @@
     }
 
     void destroyInTransaction() {
-        //        if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
-        Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(8));
-        //        }
+        if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+            Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(8));
+        }
         try {
             if (mSurfaceControl != null) {
                 mSurfaceControl.destroy();
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 4c9211a..d0c73d3 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1352,7 +1352,7 @@
                 }
 
                 final boolean drawnBeforeRestoring = wtoken.allDrawn;
-                wtoken.restoreSavedSurfaces();
+                wtoken.restoreSavedSurfaceForInterestingWindows();
 
                 if (!wtoken.allDrawn && !wtoken.startingDisplayed && !wtoken.startingMoved) {
                     return false;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 00e71f2..5f9bb9a 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -28,14 +28,13 @@
 import java.util.ArrayList;
 
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+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_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
-import static android.view.WindowManagerPolicy.TRANSIT_EXIT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
-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.TAG_WITH_CLASS_NAME;
@@ -43,12 +42,11 @@
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
 
 /**
- * Container of a set of related windows in the window manager.  Often this
- * is an AppWindowToken, which is the handle for an Activity that it uses
- * to display windows.  For nested windows, there is a WindowToken created for
- * the parent window to manage its children.
+ * Container of a set of related windows in the window manager. Often this is an AppWindowToken,
+ * which is the handle for an Activity that it uses to display windows. For nested windows, there is
+ * a WindowToken created for the parent window to manage its children.
  */
-class WindowToken {
+class WindowToken extends WindowContainer {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowToken" : TAG_WM;
 
     // The window manager!
@@ -67,9 +65,6 @@
     // For printing.
     String stringName;
 
-    // All of the windows associated with this token.
-    protected final WindowList windows = new WindowList();
-
     // Is key dispatching paused for this token?
     boolean paused = false;
 
@@ -96,18 +91,12 @@
     }
 
     void removeAllWindows() {
-        for (int winNdx = windows.size() - 1; winNdx >= 0;
-                // WindowState#removeIfPossible() at bottom of loop may remove multiple entries from
-                // allAppWindows if the window to be removed has child windows. It also may not
-                // remove any windows from allAppWindows at all if win is exiting and currently
-                // animating away. This ensures that winNdx is monotonically decreasing and never
-                // beyond allAppWindows bounds.
-                winNdx = Math.min(winNdx - 1, windows.size() - 1)) {
-            WindowState win = windows.get(winNdx);
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState win = (WindowState) mChildren.get(i);
             if (DEBUG_WINDOW_MOVEMENT) Slog.w(TAG_WM, "removeAllWindows: removing win=" + win);
             win.removeIfPossible();
         }
-        windows.clear();
+        mChildren.clear();
     }
 
     void setExiting() {
@@ -115,30 +104,20 @@
             return;
         }
 
-        boolean delayed = false;
-        final int count = windows.size();
+        final int count = mChildren.size();
         boolean changed = false;
+        boolean delayed = false;
         DisplayContent displayContent = null;
 
         for (int i = 0; i < count; i++) {
-            final WindowState win = windows.get(i);
-            displayContent = win.getDisplayContent();
-
+            final WindowState win = (WindowState) mChildren.get(i);
             if (win.mWinAnimator.isAnimationSet()) {
                 delayed = true;
+                // TODO: This is technically wrong as a token can have windows on multi-displays
+                // currently. That will change moving forward though.
+                displayContent = win.getDisplayContent();
             }
-
-            if (win.isVisibleNow()) {
-                win.mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
-                //TODO (multidisplay): Magnification is supported only for the default
-                if (mService.mAccessibilityController != null && win.isDefaultDisplay()) {
-                    mService.mAccessibilityController.onWindowTransitionLocked(win, TRANSIT_EXIT);
-                }
-                changed = true;
-                if (displayContent != null) {
-                    displayContent.layoutNeeded = true;
-                }
-            }
+            changed |= win.onSetAppExiting();
         }
 
         hidden = true;
@@ -155,14 +134,11 @@
 
     int adjustAnimLayer(int adj) {
         int highestAnimLayer = -1;
-        for (int j = windows.size() - 1; j >= 0; j--) {
-            final WindowState w = windows.get(j);
-            w.adjustAnimLayer(adj);
-            final int animLayer = w.mWinAnimator.mAnimLayer;
-            if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
-                    "adjustAnimLayer win " + w + " anim layer: " + animLayer);
-            if (animLayer > highestAnimLayer) {
-                highestAnimLayer = animLayer;
+        for (int j = mChildren.size() - 1; j >= 0; j--) {
+            final WindowState w = (WindowState) mChildren.get(j);
+            final int winHighestAnimLayer = w.adjustAnimLayer(adj);
+            if (winHighestAnimLayer > highestAnimLayer) {
+                highestAnimLayer = winHighestAnimLayer;
             }
             if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
                 mService.mLayersController.setInputMethodAnimLayerAdjustment(adj);
@@ -171,11 +147,12 @@
         return highestAnimLayer;
     }
 
-    private WindowState getTopWindow() {
-        if (windows.isEmpty()) {
+    /* package level access for test. */
+    WindowState getTopWindow() {
+        if (mChildren.isEmpty()) {
             return null;
         }
-        return windows.get(windows.size() - 1);
+        return (WindowState) mChildren.get(mChildren.size() - 1).getTop();
     }
 
     /**
@@ -183,9 +160,10 @@
      * @param target The window to search for.
      * @return The index of win in windows or of the window that is an ancestor of win.
      */
-    private int getWindowIndex(WindowState target) {
-        for (int i = windows.size() - 1; i >= 0; --i) {
-            final WindowState w = windows.get(i);
+    /* package level access for test. */
+    int getWindowIndex(WindowState target) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final WindowState w = (WindowState) mChildren.get(i);
             if (w == target || w.hasChild(target)) {
                 return i;
             }
@@ -198,18 +176,22 @@
      * @param displayContent The display we are interested in.
      * @return List of windows from token that are on displayContent.
      */
-    protected WindowList getTokenWindowsOnDisplay(DisplayContent displayContent) {
+    private WindowList getTokenWindowsOnDisplay(DisplayContent displayContent) {
         final WindowList windowList = new WindowList();
-        final int count = windows.size();
+        final WindowList displayWindows = displayContent.getWindowList();
+        final int count = displayWindows.size();
         for (int i = 0; i < count; i++) {
-            final WindowState win = windows.get(i);
-            if (win.getDisplayContent() == displayContent) {
+            final WindowState win = displayWindows.get(i);
+            if (win.mToken == this) {
                 windowList.add(win);
             }
         }
         return windowList;
     }
 
+    // TODO: Now that we are no longer adding child windows to token directly, the rest of the code
+    // in this method doesn't really belong here, but is it difficult to move at the moment. Need to
+    // re-evaluate when figuring-out what to do about display window list.
     private void addChildWindow(final WindowState win) {
         final DisplayContent displayContent = win.getDisplayContent();
         if (displayContent == null) {
@@ -235,30 +217,18 @@
             if (sublayer < 0) {
                 // For negative sublayers, we go below all windows in the same sublayer.
                 if (wSublayer >= sublayer) {
-                    if (!windows.contains(win)) {
-                        if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
-                        windows.add(i, win);
-                    }
                     win.addWindowToListBefore(wSublayer >= 0 ? parentWindow : w);
                     break;
                 }
             } else {
                 // For positive sublayers, we go above all windows in the same sublayer.
                 if (wSublayer > sublayer) {
-                    if (!windows.contains(win)) {
-                        if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
-                        windows.add(i, win);
-                    }
                     win.addWindowToListBefore(w);
                     break;
                 }
             }
         }
         if (i >= wCount) {
-            if (!windows.contains(win)) {
-                if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
-                windows.add(win);
-            }
             if (sublayer < 0) {
                 win.addWindowToListBefore(parentWindow);
             } else {
@@ -278,9 +248,9 @@
             } else {
                 win.addNonAppWindowToList();
             }
-            if (!windows.contains(win)) {
+            if (!mChildren.contains(win)) {
                 if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
-                windows.add(tokenWindowsPos, win);
+                mChildren.add(tokenWindowsPos, win);
             }
         } else {
             addChildWindow(win);
@@ -364,7 +334,7 @@
         for ( ; taskNdx >= 0; --taskNdx) {
             AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
             for ( ; tokenNdx >= 0; --tokenNdx) {
-                final AppWindowToken t = tokens.get(tokenNdx);
+                final WindowToken t = tokens.get(tokenNdx);
                 tokenWindowList = t.getTokenWindowsOnDisplay(displayContent);
                 final int NW = tokenWindowList.size();
                 if (NW > 0) {
@@ -452,19 +422,9 @@
     }
 
     int reAddAppWindows(DisplayContent displayContent, int index) {
-        final int count = windows.size();
+        final int count = mChildren.size();
         for (int i = 0; i < count; i++) {
-            final WindowState win = windows.get(i);
-            if (win.isChildWindow()) {
-                // The WindowState.reAddWindow below already takes care of re-adding the
-                // child windows for any parent window in this token. This is a side effect of
-                // ensuring child windows are in the same WindowToken as their parent window.
-                //
-                // TODO: Can be removed once WindowToken no longer contains child windows. i.e it is
-                // using WindowContainer which uses the hierarchy to access child windows through
-                // their parent window.
-                continue;
-            }
+            final WindowState win = (WindowState) mChildren.get(i);
             final DisplayContent winDisplayContent = win.getDisplayContent();
             if (winDisplayContent == displayContent || winDisplayContent == null) {
                 win.mDisplayContent = displayContent;
@@ -479,9 +439,9 @@
      * ordering the windows in mWindows
      */
     private int findIdxBasedOnAppTokens(WindowState win) {
-        WindowList windows = win.getWindowList();
+        final WindowList windows = win.getWindowList();
         for(int j = windows.size() - 1; j >= 0; j--) {
-            WindowState wentry = windows.get(j);
+            final WindowState wentry = windows.get(j);
             if(wentry.mAppToken == win.mAppToken) {
                 return j;
             }
@@ -489,11 +449,13 @@
         return -1;
     }
 
-    /** Return the first window in the token window list that isn't the exclude window or null. */
-    WindowState getFirstWindow(WindowState exclude) {
-        for (int i = 0; i < windows.size(); i++) {
-            WindowState w = windows.get(i);
-            if (w != exclude) {
+    /** 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 = (WindowState) mChildren.get(i);
+            if (w.mAttrs.type != TYPE_APPLICATION_STARTING) {
                 return w;
             }
         }
@@ -502,27 +464,28 @@
 
     @CallSuper
     void removeWindow(WindowState win) {
-        windows.remove(win);
+        mChildren.remove(win);
     }
 
     /** Returns true if the token windows list is empty. */
     boolean isEmpty() {
-        return windows.isEmpty();
+        return mChildren.isEmpty();
     }
 
     WindowState getReplacingWindow() {
-        for (int i = windows.size() - 1; i >= 0; i--) {
-            final WindowState win = windows.get(i);
-            if (win.mAnimatingExit && win.mWillReplaceWindow && win.mAnimateReplacingWindow) {
-                return win;
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final WindowState win = (WindowState) mChildren.get(i);
+            final WindowState replacing = win.getReplacingWindow();
+            if (replacing != null) {
+                return replacing;
             }
         }
         return null;
     }
 
     void hideWallpaperToken(boolean wasDeferred, String reason) {
-        for (int j = windows.size() - 1; j >= 0; j--) {
-            final WindowState wallpaper = windows.get(j);
+        for (int j = mChildren.size() - 1; j >= 0; j--) {
+            final WindowState wallpaper = (WindowState) mChildren.get(j);
             wallpaper.hideWallpaperWindow(wasDeferred, reason);
         }
         hidden = true;
@@ -530,8 +493,8 @@
 
     void sendWindowWallpaperCommand(
             String action, int x, int y, int z, Bundle extras, boolean sync) {
-        for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            WindowState wallpaper = windows.get(wallpaperNdx);
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = (WindowState) mChildren.get(wallpaperNdx);
             try {
                 wallpaper.mClient.dispatchWallpaperCommand(action, x, y, z, extras, sync);
                 // We only want to be synchronous with one wallpaper.
@@ -543,8 +506,8 @@
 
     void updateWallpaperOffset(int dw, int dh, boolean sync) {
         final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
-        for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            WindowState wallpaper = windows.get(wallpaperNdx);
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = (WindowState) mChildren.get(wallpaperNdx);
             if (wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, sync)) {
                 final WindowStateAnimator winAnimator = wallpaper.mWinAnimator;
                 winAnimator.computeShownFrameLocked();
@@ -564,8 +527,8 @@
         }
 
         final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
-        for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            WindowState wallpaper = windows.get(wallpaperNdx);
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = (WindowState) mChildren.get(wallpaperNdx);
             if (visible) {
                 wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
             }
@@ -587,8 +550,8 @@
         }
 
         final WallpaperController wallpaperController = mService.mWallpaperControllerLocked;
-        for (int wallpaperNdx = windows.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
-            final WindowState wallpaper = windows.get(wallpaperNdx);
+        for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
+            final WindowState wallpaper = (WindowState) mChildren.get(wallpaperNdx);
 
             if (visible) {
                 wallpaperController.updateWallpaperOffset(wallpaper, dw, dh, false);
@@ -623,15 +586,16 @@
             }
 
             // Now stick it in. For apps over wallpaper keep the wallpaper at the bottommost
-            // layer. For keyguard over wallpaper put the wallpaper under the keyguard unless
-            // the keyguard is still animating in.
+            // layer. For keyguard over wallpaper put the wallpaper under the lowest window that
+            // is currently on screen, i.e. not hidden by policy.
             int insertionIndex = 0;
             if (visible && wallpaperTarget != null) {
                 final int type = wallpaperTarget.mAttrs.type;
                 final int privateFlags = wallpaperTarget.mAttrs.privateFlags;
                 if (((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || type == TYPE_KEYGUARD_SCRIM)
                         && !mService.isKeyguardAnimatingIn()) {
-                    insertionIndex = windowList.indexOf(wallpaperTarget);
+                    insertionIndex = Math.min(windowList.indexOf(wallpaperTarget),
+                            findLowestWindowOnScreen(windowList));
                 }
             }
             if (DEBUG_WALLPAPER_LIGHT || DEBUG_WINDOW_MOVEMENT
@@ -646,10 +610,25 @@
         return changed;
     }
 
+    /**
+     * @return The index in {@param windows} of the lowest window that is currently on screen and
+     *         not hidden by the policy.
+     */
+    private int findLowestWindowOnScreen(WindowList windowList) {
+        final int size = windowList.size();
+        for (int index = 0; index < size; index++) {
+            final WindowState win = windowList.get(index);
+            if (win.isOnScreen()) {
+                return index;
+            }
+        }
+        return Integer.MAX_VALUE;
+    }
+
     boolean hasVisibleNotDrawnWallpaper() {
-        for (int j = windows.size() - 1; j >= 0; --j) {
-            final WindowState wallpaper = windows.get(j);
-            if (wallpaper.mWallpaperVisible && !wallpaper.isDrawnLw()) {
+        for (int j = mChildren.size() - 1; j >= 0; --j) {
+            final WindowState wallpaper = (WindowState) mChildren.get(j);
+            if (wallpaper.hasVisibleNotDrawnWallpaper()) {
                 return true;
             }
         }
@@ -657,14 +636,15 @@
     }
 
     int getHighestAnimLayer() {
-        int layer = -1;
-        for (int j = 0; j < windows.size(); j++) {
-            final WindowState win = windows.get(j);
-            if (win.mWinAnimator.mAnimLayer > layer) {
-                layer = win.mWinAnimator.mAnimLayer;
+        int highest = -1;
+        for (int j = 0; j < mChildren.size(); j++) {
+            final WindowState w = (WindowState) mChildren.get(j);
+            final int wLayer = w.getHighestAnimLayer();
+            if (wLayer > highest) {
+                highest = wLayer;
             }
         }
-        return layer;
+        return highest;
     }
 
     AppWindowToken asAppWindowToken() {
@@ -674,7 +654,7 @@
     }
 
     void dump(PrintWriter pw, String prefix) {
-        pw.print(prefix); pw.print("windows="); pw.println(windows);
+        pw.print(prefix); pw.print("windows="); pw.println(mChildren);
         pw.print(prefix); pw.print("windowType="); pw.print(windowType);
                 pw.print(" hidden="); pw.print(hidden);
                 pw.print(" hasVisible="); pw.println(hasVisible);
diff --git a/services/core/jni/com_android_server_input_InputApplicationHandle.h b/services/core/jni/com_android_server_input_InputApplicationHandle.h
index 62c8570..e6f25cc 100644
--- a/services/core/jni/com_android_server_input_InputApplicationHandle.h
+++ b/services/core/jni/com_android_server_input_InputApplicationHandle.h
@@ -26,7 +26,7 @@
 
 class NativeInputApplicationHandle : public InputApplicationHandle {
 public:
-    NativeInputApplicationHandle(jweak objWeak);
+    explicit NativeInputApplicationHandle(jweak objWeak);
     virtual ~NativeInputApplicationHandle();
 
     jobject getInputApplicationHandleObjLocalRef(JNIEnv* env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9c4b94e..f5fcc64 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5883,6 +5883,8 @@
             try {
                 clearDeviceOwnerLocked(admin, deviceOwnerUserId);
                 removeActiveAdminLocked(deviceOwnerComponent, deviceOwnerUserId);
+                Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED);
+                mContext.sendBroadcastAsUser(intent, UserHandle.of(deviceOwnerUserId));
             } finally {
                 mInjector.binderRestoreCallingIdentity(ident);
             }
diff --git a/services/net/Android.mk b/services/net/Android.mk
index 920f7c0ab..408794e 100644
--- a/services/net/Android.mk
+++ b/services/net/Android.mk
@@ -5,8 +5,7 @@
 LOCAL_MODULE := services.net
 
 LOCAL_SRC_FILES += \
-    $(call all-java-files-under,java)  \
-    ../../../../system/netd/server/binder/android/net/INetd.aidl
+    $(call all-java-files-under,java)
 
 LOCAL_AIDL_INCLUDES += \
     system/netd/server/binder
diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
index 07cc9c0..07b26e8 100644
--- a/services/print/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java
@@ -57,6 +57,9 @@
  * spooler if needed, to make the timed remote calls, to handle
  * remote exceptions, and to bind/unbind to the remote instance as
  * needed.
+ *
+ * The calls might be blocking and need the main thread of to be unblocked to finish. Hence do not
+ * call this while holding any monitors that might need to be acquired the main thread.
  */
 final class RemotePrintSpooler {
 
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index 71f8899..65c740f 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -441,12 +441,12 @@
     }
 
     public void createPrinterDiscoverySession(@NonNull IPrinterDiscoveryObserver observer) {
+        mSpooler.clearCustomPrinterIconCache();
+
         synchronized (mLock) {
             throwIfDestroyedLocked();
 
             if (mPrinterDiscoverySession == null) {
-                mSpooler.clearCustomPrinterIconCache();
-
                 // If we do not have a session, tell all service to create one.
                 mPrinterDiscoverySession = new PrinterDiscoverySessionMediator(mContext) {
                     @Override
@@ -738,6 +738,8 @@
 
     @Override
     public void onCustomPrinterIconLoaded(PrinterId printerId, Icon icon) {
+        mSpooler.onCustomPrinterIconLoaded(printerId, icon);
+
         synchronized (mLock) {
             throwIfDestroyedLocked();
 
@@ -745,7 +747,6 @@
             if (mPrinterDiscoverySession == null) {
                 return;
             }
-            mSpooler.onCustomPrinterIconLoaded(printerId, icon);
             mPrinterDiscoverySession.onCustomPrinterIconLoadedLocked(printerId);
         }
     }
@@ -994,18 +995,21 @@
      * Prune persistent state if a print service was uninstalled
      */
     public void prunePrintServices() {
+        ArrayList<ComponentName> installedComponents;
+
         synchronized (mLock) {
-            ArrayList<ComponentName> installedComponents = getInstalledComponents();
+            installedComponents = getInstalledComponents();
 
             // Remove unnecessary entries from persistent state "disabled services"
             boolean disabledServicesUninstalled = mDisabledServices.retainAll(installedComponents);
             if (disabledServicesUninstalled) {
                 writeDisabledPrintServicesLocked(mDisabledServices);
             }
-
-            // Remove unnecessary entries from persistent state "approved services"
-            mSpooler.pruneApprovedPrintServices(installedComponents);
         }
+
+        // Remove unnecessary entries from persistent state "approved services"
+        mSpooler.pruneApprovedPrintServices(installedComponents);
+
     }
 
     private void onConfigurationChangedLocked() {
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-on.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-on.xml
new file mode 100644
index 0000000..034411e
--- /dev/null
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-on.xml
@@ -0,0 +1,3 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policy-list version="10" restrictBackground="true" >
+</policy-list>
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-off.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-off.xml
new file mode 100644
index 0000000..5b1c03c
--- /dev/null
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-off.xml
@@ -0,0 +1,4 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policy-list version="10" restrictBackground="false">
+  <uid-policy uid="10004" policy="1" />
+</policy-list>
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-on.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-on.xml
new file mode 100644
index 0000000..bec2371
--- /dev/null
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-on.xml
@@ -0,0 +1,4 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policy-list version="10" restrictBackground="true">
+  <uid-policy uid="10004" policy="1" />
+</policy-list>
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-off.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-off.xml
new file mode 100644
index 0000000..196ca28
--- /dev/null
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-off.xml
@@ -0,0 +1,4 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policy-list version="10" restrictBackground="false">
+  <uid-policy uid="10004" policy="4" />
+</policy-list>
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-on.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-on.xml
new file mode 100644
index 0000000..4b7724c
--- /dev/null
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-on.xml
@@ -0,0 +1,4 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policy-list version="10" restrictBackground="true">
+  <uid-policy uid="10004" policy="4" />
+</policy-list>
diff --git a/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java b/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java
index 13657ab..6b5be580 100644
--- a/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java
+++ b/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java
@@ -44,7 +44,17 @@
 
     private final List<BroadcastInterceptor> mInterceptors = Lists.newArrayList();
 
-    public class BroadcastInterceptor extends AbstractFuture<Intent> {
+    abstract class FutureIntent extends AbstractFuture<Intent> {
+        public void assertNotReceived()
+                throws InterruptedException, ExecutionException {
+            assertNotReceived(5, TimeUnit.SECONDS);
+        }
+
+        public abstract void assertNotReceived(long timeout, TimeUnit unit)
+                throws InterruptedException, ExecutionException;
+    }
+
+    public class BroadcastInterceptor extends FutureIntent {
         private final BroadcastReceiver mReceiver;
         private final IntentFilter mFilter;
 
@@ -76,17 +86,32 @@
                 throw new RuntimeException(e);
             }
         }
+
+        @Override
+        public void assertNotReceived()
+            throws InterruptedException, ExecutionException {
+            assertNotReceived(5, TimeUnit.SECONDS);
+        }
+
+        public void assertNotReceived(long timeout, TimeUnit unit)
+                throws InterruptedException, ExecutionException {
+            try {
+                final Intent intent = get(timeout, unit);
+                throw new AssertionError("Received intent: " + intent);
+            } catch (TimeoutException e) {
+            }
+        }
     }
 
     public BroadcastInterceptingContext(Context base) {
         super(base);
     }
 
-    public Future<Intent> nextBroadcastIntent(String action) {
+    public FutureIntent nextBroadcastIntent(String action) {
         return nextBroadcastIntent(new IntentFilter(action));
     }
 
-    public Future<Intent> nextBroadcastIntent(IntentFilter filter) {
+    public FutureIntent nextBroadcastIntent(IntentFilter filter) {
         final BroadcastInterceptor interceptor = new BroadcastInterceptor(null, filter);
         synchronized (mInterceptors) {
             mInterceptors.add(interceptor);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 064b9159..92d4c46 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -52,9 +52,11 @@
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.Manifest;
 import android.app.ActivityManager;
 import android.app.IActivityManager;
 import android.app.INotificationManager;
@@ -64,9 +66,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.Signature;
+import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.INetworkManagementEventObserver;
 import android.net.INetworkPolicyListener;
@@ -84,12 +88,14 @@
 import android.os.PowerManagerInternal;
 import android.os.UserHandle;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.text.TextUtils;
 import android.text.format.Time;
 import android.util.Log;
 import android.util.TrustedTime;
 
+import com.android.server.BroadcastInterceptingContext.FutureIntent;
 import com.android.server.net.NetworkPolicyManagerInternal;
 import com.android.server.net.NetworkPolicyManagerService;
 
@@ -136,6 +142,7 @@
  * Tests for {@link NetworkPolicyManagerService}.
  */
 @RunWith(AndroidJUnit4.class)
+@MediumTest
 public class NetworkPolicyManagerServiceTest {
     private static final String TAG = "NetworkPolicyManagerServiceTest";
 
@@ -167,6 +174,7 @@
     private @Mock IConnectivityManager mConnManager;
     private @Mock INotificationManager mNotifManager;
     private @Mock PackageManager mPackageManager;
+    private @Mock IPackageManager mIpm;
 
     private IUidObserver mUidObserver;
     private INetworkManagementEventObserver mNetworkObserver;
@@ -240,7 +248,7 @@
         }).when(mActivityManager).registerUidObserver(any(), anyInt());
 
         mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
-                mNetworkManager, mTime, mPolicyDir, true);
+                mNetworkManager, mIpm, mTime, mPolicyDir, true);
         mService.bindConnectivityManager(mConnManager);
         mService.bindNotificationManager(mNotifManager);
         mPolicyListener = new NetworkPolicyListenerAnswer(mService);
@@ -275,7 +283,7 @@
         mService.systemReady();
 
         // catch INetworkManagementEventObserver during systemReady()
-        ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
+        final ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
               ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
         verify(mNetworkManager).registerObserver(networkObserver.capture());
         mNetworkObserver = networkObserver.getValue();
@@ -295,6 +303,193 @@
     }
 
     @Test
+    public void testTurnRestrictBackgroundOn() throws Exception {
+        assertRestrictBackgroundOff(); // Sanity check.
+        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
+        setRestrictBackground(true);
+        assertRestrictBackgroundChangedReceived(futureIntent, null);
+    }
+
+    @Test
+    @NetPolicyXml("restrict-background-on.xml")
+    public void testTurnRestrictBackgroundOff() throws Exception {
+        assertRestrictBackgroundOn(); // Sanity check.
+        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
+        setRestrictBackground(false);
+        assertRestrictBackgroundChangedReceived(futureIntent, null);
+    }
+
+    /**
+     * Adds whitelist when restrict background is on - app should receive an intent.
+     */
+    @Test
+    @NetPolicyXml("restrict-background-on.xml")
+    public void testAddRestrictBackgroundWhitelist_restrictBackgroundOn() throws Exception {
+        assertRestrictBackgroundOn(); // Sanity check.
+        addRestrictBackgroundWhitelist(true);
+    }
+
+    /**
+     * Adds whitelist when restrict background is off - app should not receive an intent.
+     */
+    @Test
+    public void testAddRestrictBackgroundWhitelist_restrictBackgroundOff() throws Exception {
+        assertRestrictBackgroundOff(); // Sanity check.
+        addRestrictBackgroundWhitelist(false);
+    }
+
+    private void addRestrictBackgroundWhitelist(boolean expectIntent) throws Exception {
+        assertWhitelistUids(); // Sanity check.
+        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
+        mPolicyListener.expect().onRestrictBackgroundWhitelistChanged(anyInt(), anyBoolean());
+
+        mService.addRestrictBackgroundWhitelistedUid(UID_A);
+
+        assertWhitelistUids(UID_A);
+        mPolicyListener.waitAndVerify().onRestrictBackgroundWhitelistChanged(APP_ID_A, true);
+        mPolicyListener.verifyNotCalled().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
+        if (expectIntent) {
+            assertRestrictBackgroundChangedReceived(futureIntent, PKG_NAME_A);
+        } else {
+            futureIntent.assertNotReceived();
+        }
+    }
+
+    /**
+     * Removes whitelist when restrict background is on - app should receive an intent.
+     */
+    @Test
+    @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml")
+    public void testRemoveRestrictBackgroundWhitelist_restrictBackgroundOn() throws Exception {
+        assertRestrictBackgroundOn(); // Sanity check.
+        removeRestrictBackgroundWhitelist(true);
+    }
+
+    /**
+     * Removes whitelist when restrict background is off - app should not receive an intent.
+     */
+    @Test
+    @NetPolicyXml("uidA-whitelisted-restrict-background-off.xml")
+    public void testRemoveRestrictBackgroundWhitelist_restrictBackgroundOff() throws Exception {
+        assertRestrictBackgroundOff(); // Sanity check.
+        removeRestrictBackgroundWhitelist(false);
+    }
+
+    private void removeRestrictBackgroundWhitelist(boolean expectIntent) throws Exception {
+        assertWhitelistUids(UID_A); // Sanity check.
+        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
+        mPolicyListener.expect().onRestrictBackgroundWhitelistChanged(anyInt(), anyBoolean());
+
+        mService.removeRestrictBackgroundWhitelistedUid(UID_A);
+
+        assertWhitelistUids();
+        mPolicyListener.waitAndVerify().onRestrictBackgroundWhitelistChanged(APP_ID_A, false);
+        mPolicyListener.verifyNotCalled().onRestrictBackgroundBlacklistChanged(APP_ID_A, false);
+        if (expectIntent) {
+            assertRestrictBackgroundChangedReceived(futureIntent, PKG_NAME_A);
+        } else {
+            futureIntent.assertNotReceived();
+        }
+    }
+
+    /**
+     * Adds blacklist when restrict background is on - app should receive an intent.
+     */
+    @Test
+    @NetPolicyXml("restrict-background-on.xml")
+    public void testAddRestrictBackgroundBlacklist_restrictBackgroundOn() throws Exception {
+        assertRestrictBackgroundOn(); // Sanity check.
+        addRestrictBackgroundBlacklist(true);
+    }
+
+    /**
+     * Adds blacklist when restrict background is off - app should receive an intent.
+     */
+    @Test
+    public void testAddRestrictBackgroundBlacklist_restrictBackgroundOff() throws Exception {
+        assertRestrictBackgroundOff(); // Sanity check.
+        addRestrictBackgroundBlacklist(true);
+    }
+
+    private void addRestrictBackgroundBlacklist(boolean expectIntent) throws Exception {
+        assertUidPolicy(UID_A, POLICY_NONE); // Sanity check.
+        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
+        mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
+
+        mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+
+        assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+        mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
+        mPolicyListener.verifyNotCalled().onRestrictBackgroundWhitelistChanged(APP_ID_A, true);
+        if (expectIntent) {
+            assertRestrictBackgroundChangedReceived(futureIntent, PKG_NAME_A);
+        } else {
+            futureIntent.assertNotReceived();
+        }
+    }
+
+    /**
+     * Removes blacklist when restrict background is on - app should receive an intent.
+     */
+    @Test
+    @NetPolicyXml("uidA-blacklisted-restrict-background-on.xml")
+    public void testRemoveRestrictBackgroundBlacklist_restrictBackgroundOn() throws Exception {
+        assertRestrictBackgroundOn(); // Sanity check.
+        removeRestrictBackgroundBlacklist(true);
+    }
+
+    /**
+     * Removes blacklist when restrict background is off - app should receive an intent.
+     */
+    @Test
+    @NetPolicyXml("uidA-blacklisted-restrict-background-off.xml")
+    public void testRemoveRestrictBackgroundBlacklist_restrictBackgroundOff() throws Exception {
+        assertRestrictBackgroundOff(); // Sanity check.
+        removeRestrictBackgroundBlacklist(true);
+    }
+
+    private void removeRestrictBackgroundBlacklist(boolean expectIntent) throws Exception {
+        assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND); // Sanity check.
+        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
+        mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
+
+        mService.setUidPolicy(UID_A, POLICY_NONE);
+
+        assertUidPolicy(UID_A, POLICY_NONE);
+        mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, false);
+        mPolicyListener.verifyNotCalled().onRestrictBackgroundWhitelistChanged(APP_ID_A, false);
+        if (expectIntent) {
+            assertRestrictBackgroundChangedReceived(futureIntent, PKG_NAME_A);
+        } else {
+            futureIntent.assertNotReceived();
+        }
+    }
+
+    @Test
+    @NetPolicyXml("uidA-blacklisted-restrict-background-on.xml")
+    public void testBlacklistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
+        // Sanity checks.
+        assertRestrictBackgroundOn();
+        assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
+
+        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
+        setRestrictBackground(true);
+        futureIntent.assertNotReceived();
+    }
+
+    @Test
+    @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml")
+    public void testWhitelistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
+        // Sanity checks.
+        assertRestrictBackgroundOn();
+        assertWhitelistUids(UID_A);
+
+        final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
+        setRestrictBackground(true);
+        futureIntent.assertNotReceived();
+    }
+
+    @Test
     @NetPolicyXml("restrict-background-lists-whitelist-format.xml")
     public void testRestrictBackgroundLists_whitelistFormat() throws Exception {
         restrictBackgroundListsTest();
@@ -771,6 +966,11 @@
         return futureAnswer;
     }
 
+    private void expectHasInternetPermission(int uid, boolean hasIt) throws Exception {
+        when(mIpm.checkUidPermission(Manifest.permission.INTERNET, uid)).thenReturn(
+                hasIt ? PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
+    }
+
     private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception {
         verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes);
     }
@@ -857,6 +1057,27 @@
         assertContainsInAnyOrder(mService.getRestrictBackgroundWhitelistedUids(), uids);
     }
 
+    private void assertRestrictBackgroundOn() throws Exception {
+        assertTrue("restrictBackground should be set", mService.getRestrictBackground());
+    }
+
+    private void assertRestrictBackgroundOff() throws Exception {
+        assertFalse("restrictBackground should not be set", mService.getRestrictBackground());
+    }
+
+    private FutureIntent newRestrictBackgroundChangedFuture() {
+        return mServiceContext
+                .nextBroadcastIntent(ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED);
+    }
+
+    private void assertRestrictBackgroundChangedReceived(Future<Intent> future,
+            String expectedPackage) throws Exception {
+        final String action = ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
+        final Intent intent = future.get(5, TimeUnit.SECONDS);
+        assertNotNull("Didn't get a " + action + "intent in 5 seconds");
+        assertEquals("Wrong package on " + action + " intent", expectedPackage, intent.getPackage());
+    }
+
     // TODO: replace by Truth, Hamcrest, or a similar tool.
     private void assertContainsInAnyOrder(int[] actual, int...expected) {
         final StringBuilder errors = new StringBuilder();
@@ -896,6 +1117,16 @@
         mElapsedRealtime += duration;
     }
 
+    private FutureIntent mRestrictBackgroundChanged;
+
+    private void setRestrictBackground(boolean flag) throws Exception {
+        // Must set expectation, otherwise NMPS will reset value to previous one.
+        when(mNetworkManager.setDataSaverModeEnabled(flag)).thenReturn(true);
+        mService.setRestrictBackground(flag);
+        // Sanity check.
+        assertEquals("restrictBackground not set", flag, mService.getRestrictBackground());
+    }
+
     /**
      * Creates a mock and registers it to {@link LocalServices}.
      */
@@ -950,6 +1181,11 @@
             }
             return verify(listener, atLeastOnce());
         }
+
+        INetworkPolicyListener verifyNotCalled() {
+            return verify(listener, never());
+        }
+
     }
 
     private void setNetpolicyXml(Context context) throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityCacheTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityCacheTest.java
new file mode 100644
index 0000000..42d3b07
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityCacheTest.java
@@ -0,0 +1,568 @@
+/*
+ * 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.accessibility;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.view.accessibility.AccessibilityCache;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityInteractionClient;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityWindowInfo;
+import android.view.View;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.Arrays;
+import java.util.List;
+
+
+@RunWith(AndroidJUnit4.class)
+public class AccessibilityCacheTest {
+    private static int WINDOW_ID_1 = 0xBEEF;
+    private static int WINDOW_ID_2 = 0xFACE;
+    private static int SINGLE_VIEW_ID = 0xCAFE;
+    private static int OTHER_VIEW_ID = 0xCAB2;
+    private static int PARENT_VIEW_ID = 0xFED4;
+    private static int CHILD_VIEW_ID = 0xFEED;
+    private static int MOCK_CONNECTION_ID = 1;
+
+    AccessibilityCache mAccessibilityCache;
+    AccessibilityCache.AccessibilityNodeRefresher mAccessibilityNodeRefresher;
+
+    @Before
+    public void setUp() {
+        mAccessibilityNodeRefresher = mock(AccessibilityCache.AccessibilityNodeRefresher.class);
+        when(mAccessibilityNodeRefresher.refreshNode(anyObject(), anyBoolean())).thenReturn(true);
+        mAccessibilityCache = new AccessibilityCache(mAccessibilityNodeRefresher);
+    }
+
+    @After
+    public void tearDown() {
+        // Make sure we're recycling all of our window and node infos
+        mAccessibilityCache.clear();
+        AccessibilityInteractionClient.getInstance().clearCache();
+        assertEquals(0, AccessibilityWindowInfo.getNumInstancesInUse());
+        assertEquals(0, AccessibilityNodeInfo.getNumInstancesInUse());
+    }
+
+    @Test
+    public void testEmptyCache_returnsNull() {
+        assertNull(mAccessibilityCache.getNode(0, 0));
+        assertNull(mAccessibilityCache.getWindows());
+        assertNull(mAccessibilityCache.getWindow(0));
+    }
+
+    @Test
+    public void testEmptyCache_clearDoesntCrash() {
+        mAccessibilityCache.clear();
+    }
+
+    @Test
+    public void testEmptyCache_a11yEventsHaveNoEffect() {
+        AccessibilityEvent event = AccessibilityEvent.obtain();
+        int[] a11yEventTypes = {
+                AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED,
+                AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED,
+                AccessibilityEvent.TYPE_VIEW_FOCUSED,
+                AccessibilityEvent.TYPE_VIEW_SELECTED,
+                AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED,
+                AccessibilityEvent.TYPE_VIEW_CLICKED,
+                AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
+                AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
+                AccessibilityEvent.TYPE_VIEW_SCROLLED,
+                AccessibilityEvent.TYPE_WINDOWS_CHANGED,
+                AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED};
+        for (int i = 0; i < a11yEventTypes.length; i++) {
+            event.setEventType(a11yEventTypes[i]);
+            mAccessibilityCache.onAccessibilityEvent(event);
+        }
+    }
+
+    @Test
+    public void addThenGetWindow_returnsEquivalentButNotSameWindow() {
+        AccessibilityWindowInfo windowInfo = null, copyOfInfo = null, windowFromCache = null;
+        try {
+            windowInfo = AccessibilityWindowInfo.obtain();
+            windowInfo.setId(WINDOW_ID_1);
+            mAccessibilityCache.addWindow(windowInfo);
+            // Make a copy
+            copyOfInfo = AccessibilityWindowInfo.obtain(windowInfo);
+            windowInfo.setId(WINDOW_ID_2); // Simulate recycling and reusing the original info
+            windowFromCache = mAccessibilityCache.getWindow(WINDOW_ID_1);
+            assertEquals(copyOfInfo, windowFromCache);
+        } finally {
+            windowFromCache.recycle();
+            windowInfo.recycle();
+            copyOfInfo.recycle();
+        }
+    }
+
+    @Test
+    public void addWindowThenClear_noLongerInCache() {
+        putWindowWithIdInCache(WINDOW_ID_1);
+        mAccessibilityCache.clear();
+        assertNull(mAccessibilityCache.getWindow(WINDOW_ID_1));
+    }
+
+    @Test
+    public void addWindowGetOtherId_returnsNull() {
+        putWindowWithIdInCache(WINDOW_ID_1);
+        assertNull(mAccessibilityCache.getWindow(WINDOW_ID_1 + 1));
+    }
+
+    @Test
+    public void addWindowThenGetWindows_returnsNull() {
+        putWindowWithIdInCache(WINDOW_ID_1);
+        assertNull(mAccessibilityCache.getWindows());
+    }
+
+    @Test
+    public void setWindowsThenGetWindows_returnsInDecreasingLayerOrder() {
+        AccessibilityWindowInfo windowInfo1 = null, windowInfo2 = null;
+        AccessibilityWindowInfo window1Out = null, window2Out = null;
+        List<AccessibilityWindowInfo> windowsOut = null;
+        try {
+            windowInfo1 = AccessibilityWindowInfo.obtain();
+            windowInfo1.setId(WINDOW_ID_1);
+            windowInfo1.setLayer(5);
+            windowInfo2 = AccessibilityWindowInfo.obtain();
+            windowInfo2.setId(WINDOW_ID_2);
+            windowInfo2.setLayer(windowInfo1.getLayer() + 1);
+            List<AccessibilityWindowInfo> windowsIn = Arrays.asList(windowInfo1, windowInfo2);
+            mAccessibilityCache.setWindows(windowsIn);
+
+            windowsOut = mAccessibilityCache.getWindows();
+            window1Out = mAccessibilityCache.getWindow(WINDOW_ID_1);
+            window2Out = mAccessibilityCache.getWindow(WINDOW_ID_2);
+
+            assertEquals(2, windowsOut.size());
+            assertEquals(windowInfo2, windowsOut.get(0));
+            assertEquals(windowInfo1, windowsOut.get(1));
+            assertEquals(windowInfo1, window1Out);
+            assertEquals(windowInfo2, window2Out);
+        } finally {
+            window1Out.recycle();
+            window2Out.recycle();
+            windowInfo1.recycle();
+            windowInfo2.recycle();
+            for (AccessibilityWindowInfo windowInfo : windowsOut) {
+                windowInfo.recycle();
+            }
+        }
+    }
+
+    @Test
+    public void addWindowThenStateChangedEvent_noLongerInCache() {
+        putWindowWithIdInCache(WINDOW_ID_1);
+        mAccessibilityCache.onAccessibilityEvent(
+                AccessibilityEvent.obtain(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED));
+        assertNull(mAccessibilityCache.getWindow(WINDOW_ID_1));
+    }
+
+    @Test
+    public void addWindowThenWindowsChangedEvent_noLongerInCache() {
+        putWindowWithIdInCache(WINDOW_ID_1);
+        mAccessibilityCache.onAccessibilityEvent(
+                AccessibilityEvent.obtain(AccessibilityEvent.TYPE_WINDOWS_CHANGED));
+        assertNull(mAccessibilityCache.getWindow(WINDOW_ID_1));
+    }
+
+    @Test
+    public void addThenGetNode_returnsEquivalentNode() {
+        AccessibilityNodeInfo nodeInfo, nodeCopy = null, nodeFromCache = null;
+        try {
+            nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
+            long id = nodeInfo.getSourceNodeId();
+            nodeCopy = AccessibilityNodeInfo.obtain(nodeInfo);
+            mAccessibilityCache.add(nodeInfo);
+            nodeInfo.recycle();
+            nodeFromCache = mAccessibilityCache.getNode(WINDOW_ID_1, id);
+            assertEquals(nodeCopy, nodeFromCache);
+        } finally {
+            nodeFromCache.recycle();
+            nodeCopy.recycle();
+        }
+    }
+
+    @Test
+    public void overwriteThenGetNode_returnsNewNode() {
+        final CharSequence contentDescription1 = "foo";
+        final CharSequence contentDescription2 = "bar";
+        AccessibilityNodeInfo nodeInfo1 = null, nodeInfo2 = null, nodeFromCache = null;
+        try {
+            nodeInfo1 = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
+            nodeInfo1.setContentDescription(contentDescription1);
+            long id = nodeInfo1.getSourceNodeId();
+            nodeInfo2 = AccessibilityNodeInfo.obtain(nodeInfo1);
+            nodeInfo2.setContentDescription(contentDescription2);
+            mAccessibilityCache.add(nodeInfo1);
+            mAccessibilityCache.add(nodeInfo2);
+            nodeFromCache = mAccessibilityCache.getNode(WINDOW_ID_1, id);
+            assertEquals(nodeInfo2, nodeFromCache);
+            assertEquals(contentDescription2, nodeFromCache.getContentDescription());
+        } finally {
+            nodeFromCache.recycle();
+            nodeInfo2.recycle();
+            nodeInfo1.recycle();
+        }
+    }
+
+    @Test
+    public void nodesInDifferentWindowWithSameId_areKeptSeparate() {
+        final CharSequence contentDescription1 = "foo";
+        final CharSequence contentDescription2 = "bar";
+        AccessibilityNodeInfo nodeInfo1 = null, nodeInfo2 = null,
+                node1FromCache = null, node2FromCache = null;
+        try {
+            nodeInfo1 = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
+            nodeInfo1.setContentDescription(contentDescription1);
+            long id = nodeInfo1.getSourceNodeId();
+            nodeInfo2 = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_2);
+            nodeInfo2.setContentDescription(contentDescription2);
+            assertEquals(id, nodeInfo2.getSourceNodeId());
+            mAccessibilityCache.add(nodeInfo1);
+            mAccessibilityCache.add(nodeInfo2);
+            node1FromCache = mAccessibilityCache.getNode(WINDOW_ID_1, id);
+            node2FromCache = mAccessibilityCache.getNode(WINDOW_ID_2, id);
+            assertEquals(nodeInfo1, node1FromCache);
+            assertEquals(nodeInfo2, node2FromCache);
+            assertEquals(nodeInfo1.getContentDescription(), node1FromCache.getContentDescription());
+            assertEquals(nodeInfo2.getContentDescription(), node2FromCache.getContentDescription());
+        } finally {
+            node1FromCache.recycle();
+            node2FromCache.recycle();
+            nodeInfo1.recycle();
+            nodeInfo2.recycle();
+        }
+    }
+
+    @Test
+    public void addNodeThenClear_nodeIsRemoved() {
+        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
+        long id = nodeInfo.getSourceNodeId();
+        mAccessibilityCache.add(nodeInfo);
+        nodeInfo.recycle();
+        mAccessibilityCache.clear();
+        assertNull(mAccessibilityCache.getNode(WINDOW_ID_1, id));
+    }
+
+    @Test
+    public void windowStateChangeAndWindowsChangedEvents_clearsNode() {
+        assertEventTypeClearsNode(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+        assertEventTypeClearsNode(AccessibilityEvent.TYPE_WINDOWS_CHANGED);
+    }
+
+    @Test
+    public void subTreeChangeEvent_clearsNodeAndChild() {
+        AccessibilityEvent event = AccessibilityEvent
+                .obtain(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+        event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
+        event.setSource(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1));
+
+        try {
+            assertEventClearsParentAndChild(event);
+        } finally {
+            event.recycle();
+        }
+    }
+
+    @Test
+    public void scrollEvent_clearsNodeAndChild() {
+        AccessibilityEvent event = AccessibilityEvent
+                .obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
+        event.setSource(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1));
+        try {
+            assertEventClearsParentAndChild(event);
+        } finally {
+            event.recycle();
+        }
+    }
+
+    @Test
+    public void reparentNode_clearsOldParent() {
+        AccessibilityNodeInfo parentNodeInfo = getParentNode();
+        AccessibilityNodeInfo childNodeInfo = getChildNode();
+        long parentId = parentNodeInfo.getSourceNodeId();
+        mAccessibilityCache.add(parentNodeInfo);
+        mAccessibilityCache.add(childNodeInfo);
+
+        childNodeInfo.setParent(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID + 1, WINDOW_ID_1));
+        mAccessibilityCache.add(childNodeInfo);
+
+        AccessibilityNodeInfo parentFromCache = mAccessibilityCache.getNode(WINDOW_ID_1, parentId);
+        try {
+            assertNull(parentFromCache);
+        } finally {
+            parentNodeInfo.recycle();
+            childNodeInfo.recycle();
+            if (parentFromCache != null) {
+                parentFromCache.recycle();
+            }
+        }
+    }
+
+    @Test
+    public void removeChildFromParent_clearsChild() {
+        AccessibilityNodeInfo parentNodeInfo = getParentNode();
+        AccessibilityNodeInfo childNodeInfo = getChildNode();
+        long childId = childNodeInfo.getSourceNodeId();
+        mAccessibilityCache.add(parentNodeInfo);
+        mAccessibilityCache.add(childNodeInfo);
+
+        AccessibilityNodeInfo parentNodeInfoWithNoChildren =
+                getNodeWithA11yAndWindowId(PARENT_VIEW_ID, WINDOW_ID_1);
+        mAccessibilityCache.add(parentNodeInfoWithNoChildren);
+
+        AccessibilityNodeInfo childFromCache = mAccessibilityCache.getNode(WINDOW_ID_1, childId);
+        try {
+            assertNull(childFromCache);
+        } finally {
+            parentNodeInfoWithNoChildren.recycle();
+            parentNodeInfo.recycle();
+            childNodeInfo.recycle();
+            if (childFromCache != null) {
+                childFromCache.recycle();
+            }
+        }
+    }
+
+    @Test
+    public void nodeSourceOfA11yFocusEvent_getsRefreshed() {
+        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
+        nodeInfo.setAccessibilityFocused(false);
+        mAccessibilityCache.add(nodeInfo);
+        AccessibilityEvent event = AccessibilityEvent.obtain(
+                AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+        event.setSource(getMockViewWithA11yAndWindowIds(SINGLE_VIEW_ID, WINDOW_ID_1));
+        mAccessibilityCache.onAccessibilityEvent(event);
+        event.recycle();
+        try {
+            verify(mAccessibilityNodeRefresher).refreshNode(nodeInfo, true);
+        } finally {
+            nodeInfo.recycle();
+        }
+    }
+
+    @Test
+    public void nodeWithA11yFocusWhenAnotherNodeGetsFocus_getsRefreshed() {
+        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
+        nodeInfo.setAccessibilityFocused(true);
+        mAccessibilityCache.add(nodeInfo);
+        AccessibilityEvent event = AccessibilityEvent.obtain(
+                AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+        event.setSource(getMockViewWithA11yAndWindowIds(OTHER_VIEW_ID, WINDOW_ID_1));
+        mAccessibilityCache.onAccessibilityEvent(event);
+        event.recycle();
+        try {
+            verify(mAccessibilityNodeRefresher).refreshNode(nodeInfo, true);
+        } finally {
+            nodeInfo.recycle();
+        }
+    }
+
+    @Test
+    public void nodeWithA11yFocusClearsIt_refreshes() {
+        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
+        nodeInfo.setAccessibilityFocused(true);
+        mAccessibilityCache.add(nodeInfo);
+        AccessibilityEvent event = AccessibilityEvent.obtain(
+                AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+        event.setSource(getMockViewWithA11yAndWindowIds(SINGLE_VIEW_ID, WINDOW_ID_1));
+        mAccessibilityCache.onAccessibilityEvent(event);
+        event.recycle();
+        try {
+            verify(mAccessibilityNodeRefresher).refreshNode(nodeInfo, true);
+        } finally {
+            nodeInfo.recycle();
+        }
+    }
+
+    @Test
+    public void nodeSourceOfInputFocusEvent_getsRefreshed() {
+        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
+        nodeInfo.setFocused(false);
+        mAccessibilityCache.add(nodeInfo);
+        AccessibilityEvent event = AccessibilityEvent.obtain(
+                AccessibilityEvent.TYPE_VIEW_FOCUSED);
+        event.setSource(getMockViewWithA11yAndWindowIds(SINGLE_VIEW_ID, WINDOW_ID_1));
+        mAccessibilityCache.onAccessibilityEvent(event);
+        event.recycle();
+        try {
+            verify(mAccessibilityNodeRefresher).refreshNode(nodeInfo, true);
+        } finally {
+            nodeInfo.recycle();
+        }
+    }
+
+    @Test
+    public void nodeWithInputFocusWhenAnotherNodeGetsFocus_getsRefreshed() {
+        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
+        nodeInfo.setFocused(true);
+        mAccessibilityCache.add(nodeInfo);
+        AccessibilityEvent event = AccessibilityEvent.obtain(
+                AccessibilityEvent.TYPE_VIEW_FOCUSED);
+        event.setSource(getMockViewWithA11yAndWindowIds(OTHER_VIEW_ID, WINDOW_ID_1));
+        mAccessibilityCache.onAccessibilityEvent(event);
+        event.recycle();
+        try {
+            verify(mAccessibilityNodeRefresher).refreshNode(nodeInfo, true);
+        } finally {
+            nodeInfo.recycle();
+        }
+    }
+
+    @Test
+    public void nodeEventSaysWasSelected_getsRefreshed() {
+        assertNodeIsRefreshedWithEventType(AccessibilityEvent.TYPE_VIEW_SELECTED,
+                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+    }
+
+    @Test
+    public void nodeEventSaysHadTextChanged_getsRefreshed() {
+        assertNodeIsRefreshedWithEventType(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED,
+                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+    }
+
+    @Test
+    public void nodeEventSaysWasClicked_getsRefreshed() {
+        assertNodeIsRefreshedWithEventType(AccessibilityEvent.TYPE_VIEW_CLICKED,
+                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+    }
+
+    @Test
+    public void nodeEventSaysHadSelectionChange_getsRefreshed() {
+        assertNodeIsRefreshedWithEventType(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
+                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+    }
+
+    @Test
+    public void nodeEventSaysHadTextContentChange_getsRefreshed() {
+        assertNodeIsRefreshedWithEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
+                AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT);
+    }
+
+    @Test
+    public void nodeEventSaysHadContentDescriptionChange_getsRefreshed() {
+        assertNodeIsRefreshedWithEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
+                AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
+    }
+
+    private void assertNodeIsRefreshedWithEventType(int eventType, int contentChangeTypes) {
+        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(SINGLE_VIEW_ID, WINDOW_ID_1);
+        mAccessibilityCache.add(nodeInfo);
+        AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
+        event.setSource(getMockViewWithA11yAndWindowIds(SINGLE_VIEW_ID, WINDOW_ID_1));
+        event.setContentChangeTypes(contentChangeTypes);
+        mAccessibilityCache.onAccessibilityEvent(event);
+        event.recycle();
+        try {
+            verify(mAccessibilityNodeRefresher).refreshNode(nodeInfo, true);
+        } finally {
+            nodeInfo.recycle();
+        }
+    }
+
+    private void putWindowWithIdInCache(int id) {
+        AccessibilityWindowInfo windowInfo = AccessibilityWindowInfo.obtain();
+        windowInfo.setId(id);
+        mAccessibilityCache.addWindow(windowInfo);
+        windowInfo.recycle();
+    }
+
+    private AccessibilityNodeInfo getNodeWithA11yAndWindowId(int a11yId, int windowId) {
+        AccessibilityNodeInfo node =
+                AccessibilityNodeInfo.obtain(getMockViewWithA11yAndWindowIds(a11yId, windowId));
+        node.setConnectionId(MOCK_CONNECTION_ID);
+        return node;
+    }
+
+    private View getMockViewWithA11yAndWindowIds(int a11yId, int windowId) {
+        View mockView = mock(View.class);
+        when(mockView.getAccessibilityViewId()).thenReturn(a11yId);
+        when(mockView.getAccessibilityWindowId()).thenReturn(windowId);
+        doAnswer(new Answer<AccessibilityNodeInfo>() {
+            public AccessibilityNodeInfo answer(InvocationOnMock invocation) {
+                return AccessibilityNodeInfo.obtain((View) invocation.getMock());
+            }
+        }).when(mockView).createAccessibilityNodeInfo();
+        return mockView;
+    }
+
+    private void assertEventTypeClearsNode(int eventType) {
+        final int nodeId = 0xBEEF;
+        AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(nodeId, WINDOW_ID_1);
+        long id = nodeInfo.getSourceNodeId();
+        mAccessibilityCache.add(nodeInfo);
+        nodeInfo.recycle();
+        mAccessibilityCache.onAccessibilityEvent(AccessibilityEvent.obtain(eventType));
+        assertNull(mAccessibilityCache.getNode(WINDOW_ID_1, id));
+    }
+
+    private AccessibilityNodeInfo getParentNode() {
+        AccessibilityNodeInfo parentNodeInfo =
+                getNodeWithA11yAndWindowId(PARENT_VIEW_ID, WINDOW_ID_1);
+        parentNodeInfo.addChild(getMockViewWithA11yAndWindowIds(CHILD_VIEW_ID, WINDOW_ID_1));
+        return parentNodeInfo;
+    }
+
+    private AccessibilityNodeInfo getChildNode() {
+        AccessibilityNodeInfo childNodeInfo =
+                getNodeWithA11yAndWindowId(CHILD_VIEW_ID, WINDOW_ID_1);
+        childNodeInfo.setParent(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1));
+        return childNodeInfo;
+    }
+
+    private void assertEventClearsParentAndChild(AccessibilityEvent event) {
+        AccessibilityNodeInfo parentNodeInfo = getParentNode();
+        AccessibilityNodeInfo childNodeInfo = getChildNode();
+        long parentId = parentNodeInfo.getSourceNodeId();
+        long childId = childNodeInfo.getSourceNodeId();
+        mAccessibilityCache.add(parentNodeInfo);
+        mAccessibilityCache.add(childNodeInfo);
+
+        mAccessibilityCache.onAccessibilityEvent(event);
+        parentNodeInfo.recycle();
+        childNodeInfo.recycle();
+
+        AccessibilityNodeInfo parentFromCache = mAccessibilityCache.getNode(WINDOW_ID_1, parentId);
+        AccessibilityNodeInfo childFromCache = mAccessibilityCache.getNode(WINDOW_ID_1, childId);
+        try {
+            assertNull(parentFromCache);
+            assertNull(childFromCache);
+        } finally {
+            if (parentFromCache != null) {
+                parentFromCache.recycle();
+            }
+            if (childFromCache != null) {
+                childFromCache.recycle();
+            }
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/LingerMonitorTest.java b/services/tests/servicestests/src/com/android/server/connectivity/LingerMonitorTest.java
new file mode 100644
index 0000000..bce5787e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/connectivity/LingerMonitorTest.java
@@ -0,0 +1,349 @@
+/*
+ * 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.connectivity;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkMisc;
+import android.text.format.DateUtils;
+import com.android.internal.R;
+import com.android.server.ConnectivityService;
+import com.android.server.connectivity.NetworkNotificationManager;
+import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
+import junit.framework.TestCase;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.reset;
+
+public class LingerMonitorTest extends TestCase {
+    static final String CELLULAR = "CELLULAR";
+    static final String WIFI     = "WIFI";
+
+    static final long LOW_RATE_LIMIT = DateUtils.MINUTE_IN_MILLIS;
+    static final long HIGH_RATE_LIMIT = 0;
+
+    static final int LOW_DAILY_LIMIT = 2;
+    static final int HIGH_DAILY_LIMIT = 1000;
+
+    LingerMonitor mMonitor;
+
+    @Mock ConnectivityService mConnService;
+    @Mock Context mCtx;
+    @Mock NetworkMisc mMisc;
+    @Mock NetworkNotificationManager mNotifier;
+    @Mock Resources mResources;
+
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mCtx.getResources()).thenReturn(mResources);
+        when(mCtx.getPackageName()).thenReturn("com.android.server.connectivity");
+        when(mConnService.createNetworkMonitor(any(), any(), any(), any())).thenReturn(null);
+
+        mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT);
+    }
+
+    public void testTransitions() {
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        NetworkAgentInfo nai1 = wifiNai(100);
+        NetworkAgentInfo nai2 = cellNai(101);
+
+        assertTrue(mMonitor.isNotificationEnabled(nai1, nai2));
+        assertFalse(mMonitor.isNotificationEnabled(nai2, nai1));
+    }
+
+    public void testNotificationOnLinger() {
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
+        NetworkAgentInfo from = wifiNai(100);
+        NetworkAgentInfo to = cellNai(101);
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyNotification(from, to);
+    }
+
+    public void testToastOnLinger() {
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
+        NetworkAgentInfo from = wifiNai(100);
+        NetworkAgentInfo to = cellNai(101);
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyToast(from, to);
+    }
+
+    public void testNotificationClearedAfterDisconnect() {
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
+        NetworkAgentInfo from = wifiNai(100);
+        NetworkAgentInfo to = cellNai(101);
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyNotification(from, to);
+
+        mMonitor.noteDisconnect(to);
+        verify(mNotifier, times(1)).clearNotification(100);
+    }
+
+    public void testNotificationClearedAfterSwitchingBack() {
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
+        NetworkAgentInfo from = wifiNai(100);
+        NetworkAgentInfo to = cellNai(101);
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyNotification(from, to);
+
+        mMonitor.noteLingerDefaultNetwork(to, from);
+        verify(mNotifier, times(1)).clearNotification(100);
+    }
+
+    public void testUniqueToast() {
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
+        NetworkAgentInfo from = wifiNai(100);
+        NetworkAgentInfo to = cellNai(101);
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyToast(from, to);
+
+        mMonitor.noteLingerDefaultNetwork(to, from);
+        verify(mNotifier, times(1)).clearNotification(100);
+
+        reset(mNotifier);
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyNoNotifications();
+    }
+
+    public void testMultipleNotifications() {
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
+        NetworkAgentInfo wifi1 = wifiNai(100);
+        NetworkAgentInfo wifi2 = wifiNai(101);
+        NetworkAgentInfo cell = cellNai(102);
+
+        mMonitor.noteLingerDefaultNetwork(wifi1, cell);
+        verifyNotification(wifi1, cell);
+
+        mMonitor.noteLingerDefaultNetwork(cell, wifi2);
+        verify(mNotifier, times(1)).clearNotification(100);
+
+        reset(mNotifier);
+        mMonitor.noteLingerDefaultNetwork(wifi2, cell);
+        verifyNotification(wifi2, cell);
+    }
+
+    public void testRateLimiting() throws InterruptedException {
+        mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, LOW_RATE_LIMIT);
+
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
+        NetworkAgentInfo wifi1 = wifiNai(100);
+        NetworkAgentInfo wifi2 = wifiNai(101);
+        NetworkAgentInfo wifi3 = wifiNai(102);
+        NetworkAgentInfo cell = cellNai(103);
+
+        mMonitor.noteLingerDefaultNetwork(wifi1, cell);
+        verifyNotification(wifi1, cell);
+        reset(mNotifier);
+
+        Thread.sleep(50);
+        mMonitor.noteLingerDefaultNetwork(cell, wifi2);
+        mMonitor.noteLingerDefaultNetwork(wifi2, cell);
+        verifyNoNotifications();
+
+        Thread.sleep(50);
+        mMonitor.noteLingerDefaultNetwork(cell, wifi3);
+        mMonitor.noteLingerDefaultNetwork(wifi3, cell);
+        verifyNoNotifications();
+    }
+
+    public void testDailyLimiting() throws InterruptedException {
+        mMonitor = new TestableLingerMonitor(mCtx, mNotifier, LOW_DAILY_LIMIT, HIGH_RATE_LIMIT);
+
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
+        NetworkAgentInfo wifi1 = wifiNai(100);
+        NetworkAgentInfo wifi2 = wifiNai(101);
+        NetworkAgentInfo wifi3 = wifiNai(102);
+        NetworkAgentInfo cell = cellNai(103);
+
+        mMonitor.noteLingerDefaultNetwork(wifi1, cell);
+        verifyNotification(wifi1, cell);
+        reset(mNotifier);
+
+        Thread.sleep(50);
+        mMonitor.noteLingerDefaultNetwork(cell, wifi2);
+        mMonitor.noteLingerDefaultNetwork(wifi2, cell);
+        verifyNotification(wifi2, cell);
+        reset(mNotifier);
+
+        Thread.sleep(50);
+        mMonitor.noteLingerDefaultNetwork(cell, wifi3);
+        mMonitor.noteLingerDefaultNetwork(wifi3, cell);
+        verifyNoNotifications();
+    }
+
+    public void testUniqueNotification() {
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_NOTIFICATION);
+        NetworkAgentInfo from = wifiNai(100);
+        NetworkAgentInfo to = cellNai(101);
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyNotification(from, to);
+
+        mMonitor.noteLingerDefaultNetwork(to, from);
+        verify(mNotifier, times(1)).clearNotification(100);
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyNotification(from, to);
+    }
+
+    public void testIgnoreNeverValidatedNetworks() {
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        NetworkAgentInfo from = wifiNai(100);
+        NetworkAgentInfo to = cellNai(101);
+        from.everValidated = false;
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyNoNotifications();
+    }
+
+    public void testIgnoreCurrentlyValidatedNetworks() {
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        NetworkAgentInfo from = wifiNai(100);
+        NetworkAgentInfo to = cellNai(101);
+        from.lastValidated = true;
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyNoNotifications();
+    }
+
+    public void testNoNotificationType() {
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
+        setNotificationSwitch();
+        NetworkAgentInfo from = wifiNai(100);
+        NetworkAgentInfo to = cellNai(101);
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyNoNotifications();
+    }
+
+    public void testNoTransitionToNotify() {
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_NONE);
+        setNotificationSwitch(transition(WIFI, CELLULAR));
+        NetworkAgentInfo from = wifiNai(100);
+        NetworkAgentInfo to = cellNai(101);
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyNoNotifications();
+    }
+
+    public void testDifferentTransitionToNotify() {
+        setNotificationType(LingerMonitor.NOTIFY_TYPE_TOAST);
+        setNotificationSwitch(transition(CELLULAR, WIFI));
+        NetworkAgentInfo from = wifiNai(100);
+        NetworkAgentInfo to = cellNai(101);
+
+        mMonitor.noteLingerDefaultNetwork(from, to);
+        verifyNoNotifications();
+    }
+
+    void setNotificationSwitch(String... transitions) {
+        when(mResources.getStringArray(R.array.config_networkNotifySwitches))
+                .thenReturn(transitions);
+    }
+
+    String transition(String from, String to) {
+        return from + "-" + to;
+    }
+
+    void setNotificationType(int type) {
+        when(mResources.getInteger(R.integer.config_networkNotifySwitchType)).thenReturn(type);
+    }
+
+    void verifyNoToast() {
+        verify(mNotifier, never()).showToast(any(), any());
+    }
+
+    void verifyNoNotification() {
+        verify(mNotifier, never())
+                .showNotification(anyInt(), any(), any(), any(), any(), anyBoolean());
+    }
+
+    void verifyNoNotifications() {
+        verifyNoToast();
+        verifyNoNotification();
+    }
+
+    void verifyToast(NetworkAgentInfo from, NetworkAgentInfo to) {
+        verifyNoNotification();
+        verify(mNotifier, times(1)).showToast(from, to);
+    }
+
+    void verifyNotification(NetworkAgentInfo from, NetworkAgentInfo to) {
+        verifyNoToast();
+        verify(mNotifier, times(1)).showNotification(eq(from.network.netId),
+                eq(NotificationType.NETWORK_SWITCH), eq(from), eq(to), any(), eq(true));
+    }
+
+    NetworkAgentInfo nai(int netId, int transport, int networkType, String networkTypeName) {
+        NetworkInfo info = new NetworkInfo(networkType, 0, networkTypeName, "");
+        NetworkCapabilities caps = new NetworkCapabilities();
+        caps.addCapability(0);
+        caps.addTransportType(transport);
+        NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
+                caps, 50, mCtx, null, mMisc, null, mConnService);
+        nai.everValidated = true;
+        return nai;
+    }
+
+    NetworkAgentInfo wifiNai(int netId) {
+        return nai(netId, NetworkCapabilities.TRANSPORT_WIFI,
+                ConnectivityManager.TYPE_WIFI, WIFI);
+    }
+
+    NetworkAgentInfo cellNai(int netId) {
+        return nai(netId, NetworkCapabilities.TRANSPORT_CELLULAR,
+                ConnectivityManager.TYPE_MOBILE, CELLULAR);
+    }
+
+    public static class TestableLingerMonitor extends LingerMonitor {
+        public TestableLingerMonitor(Context c, NetworkNotificationManager n, int l, long r) {
+            super(c, n, l, r);
+        }
+        @Override protected PendingIntent createNotificationIntent() {
+            return null;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 0fd1286..01b2c3b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -839,6 +839,12 @@
         );
 
         assertFalse(dpm.isAdminActiveAsUser(admin1, UserHandle.USER_SYSTEM));
+
+        // ACTION_DEVICE_OWNER_CHANGED should be sent twice, once for setting the device owner
+        // and once for clearing it.
+        verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
+                MockUtils.checkIntentAction(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED),
+                MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
         // TODO Check other calls.
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 46ac7ce..143398f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -5359,6 +5359,12 @@
     /**
      * It's the case with preintalled apps -- when applyRestore() is called, the system
      * apps are already installed, so manifest shortcuts need to be re-published.
+     *
+     * Also, when a restore target app is already installed, and
+     * - if it has allowBackup=true, we'll restore normally, so all existing shortcuts will be
+     * replaced. (but manifest shortcuts will be re-published anyway.)  We log a warning on
+     * logcat.
+     * - if it has allowBackup=false, we don't touch any of the existing shortcuts.
      */
     public void testBackupAndRestore_appAlreadyInstalledWhenRestored() {
         // Pre-backup.  Same as testBackupAndRestore_manifestRePublished().
@@ -5390,6 +5396,19 @@
         mService.mPackageMonitor.onReceive(mServiceContext,
                 genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
 
+        // Set up shortcuts for package 3, which won't be backed up / restored.
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_3, ShortcutActivity.class.getName()),
+                R.xml.shortcut_1);
+        updatePackageVersion(CALLING_PACKAGE_3, 1);
+        mService.mPackageMonitor.onReceive(mServiceContext,
+                genPackageAddIntent(CALLING_PACKAGE_3, USER_0));
+
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertTrue(getManager().setDynamicShortcuts(list(
+                    makeShortcut("s1"))));
+        });
+
         // Make sure the manifest shortcuts have been published.
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertWith(getCallerShortcuts())
@@ -5415,6 +5434,11 @@
                     .areAllDisabled();
         });
 
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("s1", "ms1");
+        });
+
         // Backup and *without restarting the service, just call applyRestore()*.
         {
             int prevUid = mInjectedCallingUid;
@@ -5454,6 +5478,12 @@
                     .areAllNotDynamic()
             ;
         });
+
+        // Package 3 still has the same shortcuts.
+        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("s1", "ms1");
+        });
     }
 
     public void testSaveAndLoad_crossProfile() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 0a7adb0..6a434ca 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -39,6 +39,9 @@
 
 /** Test {@link UserManager} functionality. */
 public class UserManagerTest extends AndroidTestCase {
+    // Taken from UserManagerService
+    private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // 30 years
+
     private static final int REMOVE_CHECK_INTERVAL_MILLIS = 500; // 0.5 seconds
     private static final int REMOVE_TIMEOUT_MILLIS = 60 * 1000; // 60 seconds
     private static final int SWITCH_USER_TIMEOUT_MILLIS = 40 * 1000; // 40 seconds
@@ -204,18 +207,28 @@
     @MediumTest
     public void testGetUserCreationTime() throws Exception {
         final int primaryUserId = mUserManager.getPrimaryUser().id;
+        final long startTime = System.currentTimeMillis();
         UserInfo profile = createProfileForUser("Managed 1",
                 UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
+        final long endTime = System.currentTimeMillis();
         assertNotNull(profile);
-        assertTrue("creationTime must be set when the profile is created",
-                profile.creationTime > 0);
+        if (System.currentTimeMillis() > EPOCH_PLUS_30_YEARS) {
+            assertTrue("creationTime must be set when the profile is created",
+                    profile.creationTime >= startTime && profile.creationTime <= endTime);
+        } else {
+            assertTrue("creationTime must be 0 if the time is not > EPOCH_PLUS_30_years",
+                    profile.creationTime == 0);
+        }
         assertEquals(profile.creationTime, mUserManager.getUserCreationTime(
                 new UserHandle(profile.id)));
 
         long ownerCreationTime = mUserManager.getUserInfo(primaryUserId).creationTime;
         assertEquals(ownerCreationTime, mUserManager.getUserCreationTime(
                 new UserHandle(primaryUserId)));
+    }
 
+    @SmallTest
+    public void testGetUserCreationTime_nonExistentUser() throws Exception {
         try {
             int noSuchUserId = 100500;
             mUserManager.getUserCreationTime(new UserHandle(noSuchUserId));
@@ -224,7 +237,10 @@
             assertTrue("SecurityException should be thrown for nonexistent user, but was: " + e,
                     e instanceof SecurityException);
         }
+    }
 
+    @SmallTest
+    public void testGetUserCreationTime_otherUser() throws Exception {
         UserInfo user = createUser("User 1", 0);
         try {
             mUserManager.getUserCreationTime(new UserHandle(user.id));
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
new file mode 100644
index 0000000..4050795
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -0,0 +1,94 @@
+/*
+ * 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.wm;
+
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.IWindow;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+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;
+
+/**
+ * Tests for the {@link WindowState} class.
+ *
+ * Build: mmma -j32 frameworks/base/services/tests/servicestests
+ * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
+ * Run: adb shell am instrument -w -e class com.android.server.wm.AppWindowTokenTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ */
+@SmallTest
+public class AppWindowTokenTests extends AndroidTestCase {
+
+    private static WindowManagerService sWm = null;
+    private final WindowManagerPolicy mPolicy = new TestWindowManagerPolicy();
+    private final IWindow mIWindow = new TestIWindow();
+
+    @Override
+    public void setUp() throws Exception {
+        final Context context = getContext();
+        if (sWm == null) {
+            // We only want to do this once for the test process as we don't want WM to try to
+            // register a bunch of local services again.
+            sWm = WindowManagerService.main(context, null, true, false, false, mPolicy);
+        }
+    }
+
+    public void testFindMainWindow() throws Exception {
+        final TestAppWindowToken token = new TestAppWindowToken();
+
+        assertNull(token.findMainWindow());
+
+        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, token);
+        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token);
+        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token);
+        token.addWindow(window1);
+        assertEquals(window1, token.findMainWindow());
+        window1.mAnimatingExit = true;
+        assertEquals(window1, token.findMainWindow());
+        final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, token);
+        token.addWindow(window2);
+        assertEquals(window2, token.findMainWindow());
+    }
+
+    private WindowState createWindow(WindowState parent, int type, WindowToken token) {
+        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
+
+        return new WindowState(sWm, null, mIWindow, token, parent, 0, 0, attrs, 0,
+                sWm.getDefaultDisplayContentLocked(), 0);
+    }
+
+    /* Used so we can gain access to some protected members of the {@link AppWindowToken} class */
+    private class TestAppWindowToken extends AppWindowToken {
+
+        TestAppWindowToken() {
+            super(sWm, null, false);
+        }
+
+        int getWindowsCount() {
+            return mChildren.size();
+        }
+
+        boolean hasWindow(WindowState w) {
+            return mChildren.contains(w);
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
index bd7c0b3..ea8b7bb 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
@@ -20,33 +20,35 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import java.util.Comparator;
+import java.util.LinkedList;
 
 /**
  * Test class for {@link WindowContainer}.
  *
  * Build: mmma -j32 frameworks/base/services/tests/servicestests
- * Install: adb install -r out/target/product/marlin/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
+ * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
  * Run: adb shell am instrument -w -e class com.android.server.wm.WindowContainerTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
  */
 @SmallTest
 public class WindowContainerTests extends AndroidTestCase {
 
     public void testCreation() throws Exception {
-        final TestWindowContainer w = new TestWindowContainer();
+        final TestWindowContainer w = new TestWindowContainerBuilder().setLayer(0).build();
         assertNull("window must have no parent", w.getParentWindow());
         assertEquals("window must have no children", 0, w.getChildrenCount());
     }
 
     public void testAdd() throws Exception {
-        final TestWindowContainer root = new TestWindowContainer();
+        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+        final TestWindowContainer root = builder.setLayer(0).build();
 
-        final TestWindowContainer layer1 = root.addChildWindow(1);
-        final TestWindowContainer secondLayer1 = root.addChildWindow(1);
-        final TestWindowContainer layer2 = root.addChildWindow(2);
-        final TestWindowContainer layerNeg1 = root.addChildWindow(-1);
-        final TestWindowContainer layerNeg2 = root.addChildWindow(-2);
-        final TestWindowContainer secondLayerNeg1 = root.addChildWindow(-1);
-        final TestWindowContainer layer0 = root.addChildWindow(0);
+        final TestWindowContainer layer1 = root.addChildWindow(builder.setLayer(1));
+        final TestWindowContainer secondLayer1 = root.addChildWindow(builder.setLayer(1));
+        final TestWindowContainer layer2 = root.addChildWindow(builder.setLayer(2));
+        final TestWindowContainer layerNeg1 = root.addChildWindow(builder.setLayer(-1));
+        final TestWindowContainer layerNeg2 = root.addChildWindow(builder.setLayer(-2));
+        final TestWindowContainer secondLayerNeg1 = root.addChildWindow(builder.setLayer(-1));
+        final TestWindowContainer layer0 = root.addChildWindow(builder.setLayer(0));
 
         assertEquals(7, root.getChildrenCount());
 
@@ -68,13 +70,14 @@
     }
 
     public void testHasChild() throws Exception {
-        final TestWindowContainer root = new TestWindowContainer();
+        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+        final TestWindowContainer root = builder.setLayer(0).build();
 
-        final TestWindowContainer child1 = root.addChildWindow(1);
-        final TestWindowContainer child2 = root.addChildWindow(1);
-        final TestWindowContainer child11 = child1.addChildWindow(1);
-        final TestWindowContainer child12 = child1.addChildWindow(1);
-        final TestWindowContainer child21 = child2.addChildWindow(1);
+        final TestWindowContainer child1 = root.addChildWindow();
+        final TestWindowContainer child2 = root.addChildWindow();
+        final TestWindowContainer child11 = child1.addChildWindow();
+        final TestWindowContainer child12 = child1.addChildWindow();
+        final TestWindowContainer child21 = child2.addChildWindow();
 
         assertEquals(2, root.getChildrenCount());
         assertEquals(2, child1.getChildrenCount());
@@ -96,13 +99,14 @@
    }
 
     public void testRemove() throws Exception {
-        final TestWindowContainer root = new TestWindowContainer();
+        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+        final TestWindowContainer root = builder.setLayer(0).build();
 
-        final TestWindowContainer child1 = root.addChildWindow(1);
-        final TestWindowContainer child2 = root.addChildWindow(1);
-        final TestWindowContainer child11 = child1.addChildWindow(1);
-        final TestWindowContainer child12 = child1.addChildWindow(1);
-        final TestWindowContainer child21 = child2.addChildWindow(1);
+        final TestWindowContainer child1 = root.addChildWindow();
+        final TestWindowContainer child2 = root.addChildWindow();
+        final TestWindowContainer child11 = child1.addChildWindow();
+        final TestWindowContainer child12 = child1.addChildWindow();
+        final TestWindowContainer child21 = child2.addChildWindow();
 
         child12.remove();
         assertNull(child12.getParentWindow());
@@ -125,9 +129,67 @@
         assertEquals(0, root.getChildrenCount());
     }
 
+    public void testDetachFromDisplay() throws Exception {
+        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+        final TestWindowContainer root = builder.setLayer(0).build();
+
+        final TestWindowContainer child1 = root.addChildWindow(builder.setCanDetach(true));
+        final TestWindowContainer child2 = root.addChildWindow();
+        final TestWindowContainer child11 = child1.addChildWindow();
+        final TestWindowContainer child12 = child1.addChildWindow(builder.setCanDetach(true));
+        final TestWindowContainer child21 = child2.addChildWindow();
+
+        assertTrue(root.detachFromDisplay());
+        assertTrue(child1.detachFromDisplay());
+        assertFalse(child11.detachFromDisplay());
+        assertTrue(child12.detachFromDisplay());
+        assertFalse(child2.detachFromDisplay());
+        assertFalse(child21.detachFromDisplay());
+    }
+
+    public void testIsAnimating() throws Exception {
+        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+        final TestWindowContainer root = builder.setLayer(0).build();
+
+        final TestWindowContainer child1 = root.addChildWindow(builder.setIsAnimating(true));
+        final TestWindowContainer child2 = root.addChildWindow();
+        final TestWindowContainer child11 = child1.addChildWindow();
+        final TestWindowContainer child12 = child1.addChildWindow(builder.setIsAnimating(true));
+        final TestWindowContainer child21 = child2.addChildWindow();
+
+        assertTrue(root.isAnimating());
+        assertTrue(child1.isAnimating());
+        assertFalse(child11.isAnimating());
+        assertTrue(child12.isAnimating());
+        assertFalse(child2.isAnimating());
+        assertFalse(child21.isAnimating());
+    }
+
+    public void testIsVisible() throws Exception {
+        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+        final TestWindowContainer root = builder.setLayer(0).build();
+
+        final TestWindowContainer child1 = root.addChildWindow(builder.setIsVisible(true));
+        final TestWindowContainer child2 = root.addChildWindow();
+        final TestWindowContainer child11 = child1.addChildWindow();
+        final TestWindowContainer child12 = child1.addChildWindow(builder.setIsVisible(true));
+        final TestWindowContainer child21 = child2.addChildWindow();
+
+        assertTrue(root.isVisible());
+        assertTrue(child1.isVisible());
+        assertFalse(child11.isVisible());
+        assertTrue(child12.isVisible());
+        assertFalse(child2.isVisible());
+        assertFalse(child21.isVisible());
+    }
+
     /* Used so we can gain access to some protected members of the {@link WindowContainer} class */
     private class TestWindowContainer extends WindowContainer {
         private final int mLayer;
+        private final LinkedList<String> mUsers = new LinkedList();
+        private final boolean mCanDetach;
+        private boolean mIsAnimating;
+        private boolean mIsVisible;
 
         /**
          * Compares 2 window layers and returns -1 if the first is lesser than the second in terms
@@ -145,12 +207,13 @@
             return 1;
         };
 
-        TestWindowContainer() {
-            mLayer = 0;
-        }
-
-        TestWindowContainer(int layer) {
+        TestWindowContainer(int layer, LinkedList<String> users, boolean canDetach,
+                boolean isAnimating, boolean isVisible) {
             mLayer = layer;
+            mUsers.addAll(users);
+            mCanDetach = canDetach;
+            mIsAnimating = isAnimating;
+            mIsVisible = isVisible;
         }
 
         TestWindowContainer getParentWindow() {
@@ -161,15 +224,79 @@
             return mChildren.size();
         }
 
-        TestWindowContainer addChildWindow(int layer) {
-            TestWindowContainer child = new TestWindowContainer(layer);
+        TestWindowContainer addChildWindow(TestWindowContainerBuilder childBuilder) {
+            TestWindowContainer child = childBuilder.build();
             addChild(child, mWindowSubLayerComparator);
             return child;
         }
 
+        TestWindowContainer addChildWindow() {
+            return addChildWindow(new TestWindowContainerBuilder().setLayer(1));
+        }
+
         TestWindowContainer getChildAt(int index) {
             return (TestWindowContainer) mChildren.get(index);
         }
+
+        @Override
+        boolean detachFromDisplay() {
+            return super.detachFromDisplay() || mCanDetach;
+        }
+
+        @Override
+        boolean isAnimating() {
+            return mIsAnimating || super.isAnimating();
+        }
+
+        @Override
+        boolean isVisible() {
+            return mIsVisible || super.isVisible();
+        }
     }
 
+    private class TestWindowContainerBuilder {
+        private int mLayer;
+        private LinkedList<String> mUsers = new LinkedList();
+        private boolean mCanDetach;
+        private boolean mIsAnimating;
+        private boolean mIsVisible;
+
+        TestWindowContainerBuilder setLayer(int layer) {
+            mLayer = layer;
+            return this;
+        }
+
+        TestWindowContainerBuilder addUser(String user) {
+            mUsers.add(user);
+            return this;
+        }
+
+        TestWindowContainerBuilder setCanDetach(boolean canDetach) {
+            mCanDetach = canDetach;
+            return this;
+        }
+
+        TestWindowContainerBuilder setIsAnimating(boolean isAnimating) {
+            mIsAnimating = isAnimating;
+            return this;
+        }
+
+        TestWindowContainerBuilder setIsVisible(boolean isVisible) {
+            mIsVisible = isVisible;
+            return this;
+        }
+
+        TestWindowContainerBuilder reset() {
+            mLayer = 0;
+            mUsers.clear();
+            mCanDetach = false;
+            mIsAnimating = false;
+            mIsVisible = false;
+            return this;
+        }
+
+        TestWindowContainer build() {
+            return new TestWindowContainer(mLayer, mUsers, mCanDetach, mIsAnimating, mIsVisible);
+        }
+    }
 }
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 64de15d..c55cfb9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -32,7 +32,7 @@
  * Tests for the {@link WindowState} class.
  *
  * Build: mmma -j32 frameworks/base/services/tests/servicestests
- * Install: adb install -r out/target/product/angler/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
+ * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
  * Run: adb shell am instrument -w -e class com.android.server.wm.WindowStateTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
  */
 @SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
new file mode 100644
index 0000000..b907161
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
@@ -0,0 +1,172 @@
+/*
+ * 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.wm;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.IWindow;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+
+/**
+ * Tests for the {@link WindowState} class.
+ *
+ * Build: mmma -j32 frameworks/base/services/tests/servicestests
+ * Install: adb install -r out/target/product/$TARGET_PRODUCT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
+ * Run: adb shell am instrument -w -e class com.android.server.wm.WindowTokenTests com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ */
+@SmallTest
+public class WindowTokenTests extends AndroidTestCase {
+
+    private static WindowManagerService sWm = null;
+    private final WindowManagerPolicy mPolicy = new TestWindowManagerPolicy();
+    private final IWindow mIWindow = new TestIWindow();
+
+    @Override
+    public void setUp() throws Exception {
+        final Context context = getContext();
+        if (sWm == null) {
+            // We only want to do this once for the test process as we don't want WM to try to
+            // register a bunch of local services again.
+            sWm = WindowManagerService.main(context, null, true, false, false, mPolicy);
+        }
+    }
+
+    public void testAddWindow() throws Exception {
+        final TestWindowToken token = new TestWindowToken();
+
+        assertEquals(0, token.getWindowsCount());
+
+        final WindowState window1 = createWindow(null, TYPE_APPLICATION, token);
+        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token);
+        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token);
+        final WindowState window2 = createWindow(null, TYPE_APPLICATION, token);
+        final WindowState window3 = createWindow(null, TYPE_APPLICATION, token);
+
+        token.addWindow(window1);
+        // NOTE: Child windows will not be added to the token as window containers can only
+        // contain/reference their direct children.
+        token.addWindow(window11);
+        token.addWindow(window12);
+        token.addWindow(window2);
+        token.addWindow(window3);
+
+        // Should not contain the child windows that were added above.
+        assertEquals(3, token.getWindowsCount());
+        assertTrue(token.hasWindow(window1));
+        assertFalse(token.hasWindow(window11));
+        assertFalse(token.hasWindow(window12));
+        assertTrue(token.hasWindow(window2));
+        assertTrue(token.hasWindow(window3));
+    }
+
+    public void testAdjustAnimLayer() throws Exception {
+        final TestWindowToken token = new TestWindowToken();
+        final WindowState window1 = createWindow(null, TYPE_APPLICATION, token);
+        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token);
+        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token);
+        final WindowState window2 = createWindow(null, TYPE_APPLICATION, token);
+        final WindowState window3 = createWindow(null, TYPE_APPLICATION, token);
+
+        token.addWindow(window1);
+        token.addWindow(window2);
+        token.addWindow(window3);
+
+        final int adj = 50;
+        final int window2StartLayer = window2.mLayer = 100;
+        final int window3StartLayer = window3.mLayer = 200;
+        final int highestLayer = token.adjustAnimLayer(adj);
+
+        assertEquals(adj, window1.mWinAnimator.mAnimLayer);
+        assertEquals(adj, window11.mWinAnimator.mAnimLayer);
+        assertEquals(adj, window12.mWinAnimator.mAnimLayer);
+        assertEquals(window2StartLayer + adj, window2.mWinAnimator.mAnimLayer);
+        assertEquals(window3StartLayer + adj, window3.mWinAnimator.mAnimLayer);
+        assertEquals(window3StartLayer + adj, highestLayer);
+    }
+
+    public void testGetTopWindow() throws Exception {
+        final TestWindowToken token = new TestWindowToken();
+
+        assertNull(token.getTopWindow());
+
+        final WindowState window1 = createWindow(null, TYPE_APPLICATION, token);
+        token.addWindow(window1);
+        assertEquals(window1, token.getTopWindow());
+        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token);
+        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token);
+        assertEquals(window12, token.getTopWindow());
+
+        final WindowState window2 = createWindow(null, TYPE_APPLICATION, token);
+        token.addWindow(window2);
+        // Since new windows are added to the bottom of the token, we would still expect the
+        // previous one to the top.
+        assertEquals(window12, token.getTopWindow());
+    }
+
+    public void testGetWindowIndex() throws Exception {
+        final TestWindowToken token = new TestWindowToken();
+
+        final WindowState window1 = createWindow(null, TYPE_APPLICATION, token);
+        assertEquals(-1, token.getWindowIndex(window1));
+        token.addWindow(window1);
+        assertEquals(0, token.getWindowIndex(window1));
+        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token);
+        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token);
+        // Child windows should report the same index as their parents.
+        assertEquals(0, token.getWindowIndex(window11));
+        assertEquals(0, token.getWindowIndex(window12));
+
+        final WindowState window2 = createWindow(null, TYPE_APPLICATION, token);
+        assertEquals(-1, token.getWindowIndex(window2));
+        token.addWindow(window2);
+        // Since new windows are added to the bottom of the token, we would expect the added window
+        // to be at index 0.
+        assertEquals(0, token.getWindowIndex(window2));
+        assertEquals(1, token.getWindowIndex(window1));
+    }
+
+    private WindowState createWindow(WindowState parent, int type, WindowToken token) {
+        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
+
+        return new WindowState(sWm, null, mIWindow, token, parent, 0, 0, attrs, 0,
+                sWm.getDefaultDisplayContentLocked(), 0);
+    }
+
+    /* Used so we can gain access to some protected members of the {@link WindowToken} class */
+    private class TestWindowToken extends WindowToken {
+
+        TestWindowToken() {
+            super(sWm, null, 0, false);
+        }
+
+        int getWindowsCount() {
+            return mChildren.size();
+        }
+
+        boolean hasWindow(WindowState w) {
+            return mChildren.contains(w);
+        }
+    }
+}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index a093d54..2eb37df 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -327,7 +327,7 @@
      *
      * @hide
      */
-    public static final int PROPERTY_SHOW_CALLBACK_NUMBER = 1<<0;
+    public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1<<0;
 
     /**
      * Whether the call is a generic conference, where we do not know the precise state of
@@ -655,8 +655,8 @@
             builder.append("Properties:");
         }
 
-        if (can(properties, PROPERTY_SHOW_CALLBACK_NUMBER)) {
-            builder.append(isLong ? " PROPERTY_SHOW_CALLBACK_NUMBER" : " clbk");
+        if (can(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
+            builder.append(isLong ? " PROPERTY_EMERGENCY_CALLBACK_MODE" : " ecbm");
         }
 
         if (can(properties, PROPERTY_HIGH_DEF_AUDIO)) {
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index df6715d..69de89d 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -449,8 +449,8 @@
     }
 
     /**
-     * Called when a {@link Call} has received a connection event issued by the
-     * {@link ConnectionService}.
+     * Unused; to handle connection events issued by a {@link ConnectionService}, implement the
+     * {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)} callback.
      * <p>
      * See {@link Connection#sendConnectionEvent(String, Bundle)}.
      *
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 88fc78b..e27ab52 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -876,6 +876,11 @@
 
     /**
      * Flag indicating whether the carrier supports the Hold command while in an IMS call.
+     * <p>
+     * The device configuration value {@code config_device_respects_hold_carrier_config} ultimately
+     * controls whether this carrier configuration option is used.  Where
+     * {@code config_device_respects_hold_carrier_config} is false, the value of the
+     * {@link #KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL} carrier configuration option is ignored.
      * @hide
      */
     public static final String KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL = "allow_hold_in_ims_call";
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 2a490d1..04f46d9 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -61,7 +61,7 @@
     liblog \
     libcutils \
     libexpat \
-    libziparchive-host \
+    libziparchive \
     libbase
 
 aaptCFlags := -DAAPT_VERSION=\"$(BUILD_NUMBER_FROM_FILE)\"
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index b52c530..d563579 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -132,7 +132,7 @@
 	liblog \
 	libcutils \
 	libexpat \
-	libziparchive-host \
+	libziparchive \
 	libpng \
 	libbase \
 	libprotobuf-cpp-lite
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index ae5d299..21d2f64 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -201,8 +201,7 @@
 }
 
 /**
- * The default handler for collisions. A return value of -1 means keep the
- * existing value, 0 means fail, and +1 means take the incoming value.
+ * The default handler for collisions.
  *
  * Typically, a weak value will be overridden by a strong value. An existing weak
  * value will not be overridden by an incoming weak value.
@@ -219,45 +218,34 @@
  *
  * A DECL will override a USE without error. Two DECLs must match in their format for there to be
  * no error.
- *
- * Styleables: Styleables are not actual resources, but they are treated as such during the
- * compilation phase. Styleables are allowed to override each other, and their definitions merge
- * and accumulate. If both values are Styleables, we just merge them into the existing value.
  */
-int ResourceTable::resolveValueCollision(Value* existing, Value* incoming) {
-    if (Styleable* existingStyleable = valueCast<Styleable>(existing)) {
-        if (Styleable* incomingStyleable = valueCast<Styleable>(incoming)) {
-            // Styleables get merged.
-            existingStyleable->mergeWith(incomingStyleable);
-            return -1;
-        }
-    }
-
+ResourceTable::CollisionResult ResourceTable::resolveValueCollision(
+        Value* existing, Value* incoming) {
     Attribute* existingAttr = valueCast<Attribute>(existing);
     Attribute* incomingAttr = valueCast<Attribute>(incoming);
     if (!incomingAttr) {
         if (incoming->isWeak()) {
             // We're trying to add a weak resource but a resource
             // already exists. Keep the existing.
-            return -1;
+            return CollisionResult::kKeepOriginal;
         } else if (existing->isWeak()) {
             // Override the weak resource with the new strong resource.
-            return 1;
+            return CollisionResult::kTakeNew;
         }
         // The existing and incoming values are strong, this is an error
         // if the values are not both attributes.
-        return 0;
+        return CollisionResult::kConflict;
     }
 
     if (!existingAttr) {
         if (existing->isWeak()) {
             // The existing value is not an attribute and it is weak,
             // so take the incoming attribute value.
-            return 1;
+            return CollisionResult::kTakeNew;
         }
         // The existing value is not an attribute and it is strong,
         // so the incoming attribute value is an error.
-        return 0;
+        return CollisionResult::kConflict;
     }
 
     assert(incomingAttr && existingAttr);
@@ -272,20 +260,20 @@
         // The two attributes are both DECLs, but they are plain attributes
         // with the same formats.
         // Keep the strongest one.
-        return existingAttr->isWeak() ? 1 : -1;
+        return existingAttr->isWeak() ? CollisionResult::kTakeNew : CollisionResult::kKeepOriginal;
     }
 
     if (existingAttr->isWeak() && existingAttr->typeMask == android::ResTable_map::TYPE_ANY) {
         // Any incoming attribute is better than this.
-        return 1;
+        return CollisionResult::kTakeNew;
     }
 
     if (incomingAttr->isWeak() && incomingAttr->typeMask == android::ResTable_map::TYPE_ANY) {
         // The incoming attribute may be a USE instead of a DECL.
         // Keep the existing attribute.
-        return -1;
+        return CollisionResult::kKeepOriginal;
     }
-    return 0;
+    return CollisionResult::kConflict;
 }
 
 static constexpr const char* kValidNameChars = "._-";
@@ -367,7 +355,7 @@
                                     const StringPiece& product,
                                     std::unique_ptr<Value> value,
                                     const char* validChars,
-                                    const std::function<int(Value*,Value*)>& conflictResolver,
+                                    const CollisionResolverFunc& conflictResolver,
                                     IDiagnostics* diag) {
     assert(value && "value can't be nullptr");
     assert(diag && "diagnostics can't be nullptr");
@@ -431,17 +419,22 @@
         configValue->value = std::move(value);
 
     } else {
-        int collisionResult = conflictResolver(configValue->value.get(), value.get());
-        if (collisionResult > 0) {
+        switch (conflictResolver(configValue->value.get(), value.get())) {
+        case CollisionResult::kTakeNew:
             // Take the incoming value.
             configValue->value = std::move(value);
-        } else if (collisionResult == 0) {
+            break;
+
+        case CollisionResult::kConflict:
             diag->error(DiagMessage(value->getSource())
-                        << "duplicate value for resource '" << name << "' "
-                        << "with config '" << config << "'");
+                                    << "duplicate value for resource '" << name << "' "
+                                    << "with config '" << config << "'");
             diag->error(DiagMessage(configValue->value->getSource())
-                        << "resource previously defined here");
+                                    << "resource previously defined here");
             return false;
+
+        case CollisionResult::kKeepOriginal:
+            break;
         }
     }
 
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 6b52a43..df60814 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -38,8 +38,8 @@
 
 enum class SymbolState {
     kUndefined,
+    kPrivate,
     kPublic,
-    kPrivate
 };
 
 /**
@@ -185,13 +185,18 @@
 public:
     ResourceTable() = default;
 
+    enum class CollisionResult {
+        kKeepOriginal,
+        kConflict,
+        kTakeNew
+    };
+
+    using CollisionResolverFunc = std::function<CollisionResult(Value*, Value*)>;
+
     /**
      * When a collision of resources occurs, this method decides which value to keep.
-     * Returns -1 if the existing value should be chosen.
-     * Returns 0 if the collision can not be resolved (error).
-     * Returns 1 if the incoming value should be chosen.
      */
-    static int resolveValueCollision(Value* existing, Value* incoming);
+    static CollisionResult resolveValueCollision(Value* existing, Value* incoming);
 
     bool addResource(const ResourceNameRef& name,
                      const ConfigDescription& config,
@@ -299,7 +304,7 @@
                          const StringPiece& product,
                          std::unique_ptr<Value> value,
                          const char* validChars,
-                         const std::function<int(Value*,Value*)>& conflictResolver,
+                         const CollisionResolverFunc& conflictResolver,
                          IDiagnostics* diag);
 
     bool setSymbolStateImpl(const ResourceNameRef& name,
diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp
index feaca4e..4db40a6 100644
--- a/tools/aapt2/ResourceTable_test.cpp
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -118,39 +118,6 @@
     EXPECT_FALSE(attr->isWeak());
 }
 
-TEST(ResourceTable, MergeStyleables) {
-    ResourceTable table;
-
-    ASSERT_TRUE(table.addResource(
-            test::parseNameOrDie("android:styleable/Foo"),
-            ConfigDescription{}, "",
-            test::StyleableBuilder()
-                    .addItem("android:attr/bar")
-                    .addItem("android:attr/foo")
-                    .build(),
-            test::getDiagnostics()));
-
-    ASSERT_TRUE(table.addResource(
-            test::parseNameOrDie("android:styleable/Foo"),
-            ConfigDescription{}, "",
-            test::StyleableBuilder()
-                    .addItem("android:attr/bat")
-                    .addItem("android:attr/foo")
-                    .build(),
-            test::getDiagnostics()));
-
-    Styleable* styleable = test::getValue<Styleable>(&table, "android:styleable/Foo");
-    ASSERT_NE(nullptr, styleable);
-
-    std::vector<Reference> expectedRefs = {
-            Reference(test::parseNameOrDie("android:attr/bar")),
-            Reference(test::parseNameOrDie("android:attr/bat")),
-            Reference(test::parseNameOrDie("android:attr/foo")),
-    };
-
-    EXPECT_EQ(expectedRefs, styleable->entries);
-}
-
 TEST(ResourceTableTest, ProductVaryingValues) {
     ResourceTable table;
 
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index 321f776..492155d 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -18,7 +18,6 @@
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
 #include "ValueVisitor.h"
-#include "io/File.h"
 #include "util/Util.h"
 
 #include <algorithm>
@@ -66,7 +65,7 @@
     *out << "(raw string) " << *value;
 }
 
-Reference::Reference() : referenceType(Reference::Type::kResource) {
+Reference::Reference() : referenceType(Type::kResource) {
 }
 
 Reference::Reference(const ResourceNameRef& n, Type t) :
@@ -76,6 +75,10 @@
 Reference::Reference(const ResourceId& i, Type type) : id(i), referenceType(type) {
 }
 
+Reference::Reference(const ResourceNameRef& n, const ResourceId& i) :
+        name(n.toResourceName()), id(i), referenceType(Type::kResource) {
+}
+
 bool Reference::equals(const Value* value) const {
     const Reference* other = valueCast<Reference>(value);
     if (!other) {
@@ -747,8 +750,16 @@
     return a.name != b.name || a.id != b.id;
 }
 
+struct NameOnlyComparator {
+    bool operator()(const Reference& a, const Reference& b) const {
+        return a.name < b.name;
+    }
+};
+
 void Styleable::mergeWith(Styleable* other) {
-    std::set<Reference> references;
+    // Compare only names, because some References may already have their IDs assigned
+    // (framework IDs that don't change).
+    std::set<Reference, NameOnlyComparator> references;
     references.insert(entries.begin(), entries.end());
     references.insert(other->entries.begin(), other->entries.end());
     entries.clear();
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index eb7559a..5e5d1f3 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -172,6 +172,7 @@
     Reference();
     explicit Reference(const ResourceNameRef& n, Type type = Type::kResource);
     explicit Reference(const ResourceId& i, Type type = Type::kResource);
+    explicit Reference(const ResourceNameRef& n, const ResourceId& i);
 
     bool equals(const Value* value) const override;
     bool flatten(android::Res_value* outValue) const override;
diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp
index 6a35e8c..d5067b1 100644
--- a/tools/aapt2/flatten/TableFlattener.cpp
+++ b/tools/aapt2/flatten/TableFlattener.cpp
@@ -83,19 +83,19 @@
 
     void visit(Attribute* attr) override {
         {
-            Reference key = Reference(ResTable_map::ATTR_TYPE);
+            Reference key = Reference(ResourceId(ResTable_map::ATTR_TYPE));
             BinaryPrimitive val(Res_value::TYPE_INT_DEC, attr->typeMask);
             flattenEntry(&key, &val);
         }
 
         if (attr->minInt != std::numeric_limits<int32_t>::min()) {
-            Reference key = Reference(ResTable_map::ATTR_MIN);
+            Reference key = Reference(ResourceId(ResTable_map::ATTR_MIN));
             BinaryPrimitive val(Res_value::TYPE_INT_DEC, static_cast<uint32_t>(attr->minInt));
             flattenEntry(&key, &val);
         }
 
         if (attr->maxInt != std::numeric_limits<int32_t>::max()) {
-            Reference key = Reference(ResTable_map::ATTR_MAX);
+            Reference key = Reference(ResourceId(ResTable_map::ATTR_MAX));
             BinaryPrimitive val(Res_value::TYPE_INT_DEC, static_cast<uint32_t>(attr->maxInt));
             flattenEntry(&key, &val);
         }
diff --git a/tools/aapt2/integration-tests/AppOne/res/values/test.xml b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
index f4b7471..91f8bfd 100644
--- a/tools/aapt2/integration-tests/AppOne/res/values/test.xml
+++ b/tools/aapt2/integration-tests/AppOne/res/values/test.xml
@@ -29,4 +29,11 @@
         <flag name="pub" value="2" />
         <flag name="weak" value="4" />
     </attr>
+
+    <!-- Override the Widget styleable declared in StaticLibOne.
+         This should merge the two when built in overlay mode. -->
+    <declare-styleable name="Widget">
+        <attr name="android:text" />
+        <attr name="layout_width" />
+    </declare-styleable>
 </resources>
diff --git a/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml b/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
index d09a485..b4dc90b 100644
--- a/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
+++ b/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
@@ -23,5 +23,6 @@
 
     <declare-styleable name="Widget">
         <attr name="StaticLibOne_attr" />
+        <attr name="android:text" />
     </declare-styleable>
 </resources>
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 379c991..eea4306 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -55,12 +55,17 @@
     bool error = false;
     for (auto& package : table->packages) {
         // Warn of packages with an unrelated ID.
-        if (package->id && package->id.value() != 0x0 && package->id.value() != desiredPackageId) {
+        const Maybe<ResourceId>& id = package->id;
+        if (id && id.value() != 0x0 && id.value() != desiredPackageId) {
             mContext->getDiagnostics()->warn(DiagMessage(src)
                                              << "ignoring package " << package->name);
             continue;
         }
 
+        // Only merge an empty package or the package we're building.
+        // Other packages may exist, which likely contain attribute definitions.
+        // This is because at compile time it is unknown if the attributes are simply
+        // uses of the attribute or definitions.
         if (package->name.empty() || mContext->getCompilationPackage() == package->name) {
             FileMergeCallback callback;
             if (collection) {
@@ -85,8 +90,8 @@
             // mangled, then looked up at resolution time.
             // Also, when linking, we convert references with no package name to use
             // the compilation package name.
-            error |= !doMerge(src, table, package.get(),
-                              false /* mangle */, overlay, allowNew, callback);
+            error |= !doMerge(src, table, package.get(), false /* mangle */, overlay, allowNew,
+                              callback);
         }
     }
     return !error;
@@ -129,6 +134,106 @@
     return !error;
 }
 
+static bool mergeType(IAaptContext* context, const Source& src, ResourceTableType* dstType,
+                      ResourceTableType* srcType) {
+    if (dstType->symbolStatus.state < srcType->symbolStatus.state) {
+        // The incoming type's visibility is stronger, so we should override
+        // the visibility.
+        if (srcType->symbolStatus.state == SymbolState::kPublic) {
+            // Only copy the ID if the source is public, or else the ID is meaningless.
+            dstType->id = srcType->id;
+        }
+        dstType->symbolStatus = std::move(srcType->symbolStatus);
+    } else if (dstType->symbolStatus.state == SymbolState::kPublic
+            && srcType->symbolStatus.state == SymbolState::kPublic
+            && dstType->id && srcType->id
+            && dstType->id.value() != srcType->id.value()) {
+        // Both types are public and have different IDs.
+        context->getDiagnostics()->error(DiagMessage(src)
+                                         << "cannot merge type '" << srcType->type
+                                         << "': conflicting public IDs");
+        return false;
+    }
+    return true;
+}
+
+static bool mergeEntry(IAaptContext* context, const Source& src, ResourceEntry* dstEntry,
+                       ResourceEntry* srcEntry) {
+    if (dstEntry->symbolStatus.state < srcEntry->symbolStatus.state) {
+        // The incoming type's visibility is stronger, so we should override
+        // the visibility.
+        if (srcEntry->symbolStatus.state == SymbolState::kPublic) {
+            // Only copy the ID if the source is public, or else the ID is meaningless.
+            dstEntry->id = srcEntry->id;
+        }
+        dstEntry->symbolStatus = std::move(srcEntry->symbolStatus);
+    } else if (srcEntry->symbolStatus.state == SymbolState::kPublic
+            && dstEntry->symbolStatus.state == SymbolState::kPublic
+            && dstEntry->id && srcEntry->id
+            && dstEntry->id.value() != srcEntry->id.value()) {
+        // Both entries are public and have different IDs.
+        context->getDiagnostics()->error(DiagMessage(src)
+                                         << "cannot merge entry '" << srcEntry->name
+                                         << "': conflicting public IDs");
+        return false;
+    }
+    return true;
+}
+
+/**
+ * Modified CollisionResolver which will merge Styleables. Used with overlays.
+ *
+ * Styleables are not actual resources, but they are treated as such during the
+ * compilation phase. Styleables don't simply overlay each other, their definitions merge
+ * and accumulate. If both values are Styleables, we just merge them into the existing value.
+ */
+static ResourceTable::CollisionResult resolveMergeCollision(Value* existing, Value* incoming) {
+    if (Styleable* existingStyleable = valueCast<Styleable>(existing)) {
+        if (Styleable* incomingStyleable = valueCast<Styleable>(incoming)) {
+            // Styleables get merged.
+            existingStyleable->mergeWith(incomingStyleable);
+            return ResourceTable::CollisionResult::kKeepOriginal;
+        }
+    }
+    // Delegate to the default handler.
+    return ResourceTable::resolveValueCollision(existing, incoming);
+}
+
+static ResourceTable::CollisionResult mergeConfigValue(IAaptContext* context,
+                                                       const ResourceNameRef& resName,
+                                                       const bool overlay,
+                                                       ResourceConfigValue* dstConfigValue,
+                                                       ResourceConfigValue* srcConfigValue) {
+    using CollisionResult = ResourceTable::CollisionResult;
+
+    Value* dstValue = dstConfigValue->value.get();
+    Value* srcValue = srcConfigValue->value.get();
+
+    CollisionResult collisionResult;
+    if (overlay) {
+        collisionResult = resolveMergeCollision(dstValue, srcValue);
+    } else {
+        collisionResult = ResourceTable::resolveValueCollision(dstValue, srcValue);
+    }
+
+    if (collisionResult == CollisionResult::kConflict) {
+        if (overlay) {
+            return CollisionResult::kTakeNew;
+        }
+
+        // Error!
+        context->getDiagnostics()->error(DiagMessage(srcValue->getSource())
+                                         << "resource '" << resName
+                                         << "' has a conflicting value for "
+                                         << "configuration ("
+                                         << srcConfigValue->config << ")");
+        context->getDiagnostics()->note(DiagMessage(dstValue->getSource())
+                                        << "originally defined here");
+        return CollisionResult::kConflict;
+    }
+    return collisionResult;
+}
+
 bool TableMerger::doMerge(const Source& src,
                           ResourceTable* srcTable,
                           ResourceTablePackage* srcPackage,
@@ -140,115 +245,64 @@
 
     for (auto& srcType : srcPackage->types) {
         ResourceTableType* dstType = mMasterPackage->findOrCreateType(srcType->type);
-        if (srcType->symbolStatus.state == SymbolState::kPublic) {
-            if (dstType->symbolStatus.state == SymbolState::kPublic && dstType->id && srcType->id
-                    && dstType->id.value() != srcType->id.value()) {
-                // Both types are public and have different IDs.
-                mContext->getDiagnostics()->error(DiagMessage(src)
-                                                  << "can not merge type '"
-                                                  << srcType->type
-                                                  << "': conflicting public IDs");
-                error = true;
-                continue;
-            }
-
-            dstType->symbolStatus = std::move(srcType->symbolStatus);
-            dstType->id = srcType->id;
+        if (!mergeType(mContext, src, dstType, srcType.get())) {
+            error = true;
+            continue;
         }
 
         for (auto& srcEntry : srcType->entries) {
-            ResourceEntry* dstEntry;
+            std::string entryName = srcEntry->name;
             if (manglePackage) {
-                std::string mangledName = NameMangler::mangleEntry(srcPackage->name,
-                                                                   srcEntry->name);
-                if (allowNewResources) {
-                    dstEntry = dstType->findOrCreateEntry(mangledName);
-                } else {
-                    dstEntry = dstType->findEntry(mangledName);
-                }
-            } else {
-                if (allowNewResources) {
-                    dstEntry = dstType->findOrCreateEntry(srcEntry->name);
-                } else {
-                    dstEntry = dstType->findEntry(srcEntry->name);
-                }
+                entryName = NameMangler::mangleEntry(srcPackage->name, srcEntry->name);
             }
 
+            ResourceEntry* dstEntry;
+            if (allowNewResources) {
+                dstEntry = dstType->findOrCreateEntry(entryName);
+            } else {
+                dstEntry = dstType->findEntry(entryName);
+            }
+
+            const ResourceNameRef resName(srcPackage->name, srcType->type, srcEntry->name);
+
             if (!dstEntry) {
                 mContext->getDiagnostics()->error(DiagMessage(src)
-                                                  << "resource "
-                                                  << ResourceNameRef(srcPackage->name,
-                                                                     srcType->type,
-                                                                     srcEntry->name)
+                                                  << "resource " << resName
                                                   << " does not override an existing resource");
                 mContext->getDiagnostics()->note(DiagMessage(src)
                                                  << "define an <add-resource> tag or use "
-                                                    "--auto-add-overlay");
+                                                 << "--auto-add-overlay");
                 error = true;
                 continue;
             }
 
-            if (srcEntry->symbolStatus.state != SymbolState::kUndefined) {
-                if (srcEntry->symbolStatus.state == SymbolState::kPublic) {
-                    if (dstEntry->symbolStatus.state == SymbolState::kPublic &&
-                            dstEntry->id && srcEntry->id &&
-                            dstEntry->id.value() != srcEntry->id.value()) {
-                        // Both entries are public and have different IDs.
-                        mContext->getDiagnostics()->error(DiagMessage(src)
-                                                          << "can not merge entry '"
-                                                          << srcEntry->name
-                                                          << "': conflicting public IDs");
-                        error = true;
-                        continue;
-                    }
-
-                    if (srcEntry->id) {
-                        dstEntry->id = srcEntry->id;
-                    }
-                }
-
-                if (dstEntry->symbolStatus.state != SymbolState::kPublic &&
-                        dstEntry->symbolStatus.state != srcEntry->symbolStatus.state) {
-                    dstEntry->symbolStatus = std::move(srcEntry->symbolStatus);
-                }
+            if (!mergeEntry(mContext, src, dstEntry, srcEntry.get())) {
+                error = true;
+                continue;
             }
 
-            ResourceNameRef resName(mMasterPackage->name, dstType->type, dstEntry->name);
+            for (auto& srcConfigValue : srcEntry->values) {
+                using CollisionResult = ResourceTable::CollisionResult;
 
-            for (auto& srcValue : srcEntry->values) {
-                ResourceConfigValue* dstValue = dstEntry->findValue(srcValue->config,
-                                                                    srcValue->product);
-                if (dstValue) {
-                    const int collisionResult = ResourceTable::resolveValueCollision(
-                            dstValue->value.get(), srcValue->value.get());
-                    if (collisionResult == 0 && !overlay) {
-                        // Error!
-                        ResourceNameRef resourceName(srcPackage->name,
-                                                     srcType->type,
-                                                     srcEntry->name);
-
-                        mContext->getDiagnostics()->error(DiagMessage(srcValue->value->getSource())
-                                                          << "resource '" << resourceName
-                                                          << "' has a conflicting value for "
-                                                          << "configuration ("
-                                                          << srcValue->config << ")");
-                        mContext->getDiagnostics()->note(DiagMessage(dstValue->value->getSource())
-                                                         << "originally defined here");
+                ResourceConfigValue* dstConfigValue = dstEntry->findValue(srcConfigValue->config,
+                                                                          srcConfigValue->product);
+                if (dstConfigValue) {
+                    CollisionResult collisionResult = mergeConfigValue(
+                            mContext, resName, overlay, dstConfigValue, srcConfigValue.get());
+                    if (collisionResult == CollisionResult::kConflict) {
                         error = true;
                         continue;
-                    } else if (collisionResult < 0) {
-                        // Keep our existing value.
+                    } else if (collisionResult == CollisionResult::kKeepOriginal) {
                         continue;
                     }
-
+                } else {
+                    dstConfigValue = dstEntry->findOrCreateValue(srcConfigValue->config,
+                                                                 srcConfigValue->product);
                 }
 
-                if (!dstValue) {
-                    // Force create the entry if we didn't have it.
-                    dstValue = dstEntry->findOrCreateValue(srcValue->config, srcValue->product);
-                }
+                // Continue if we're taking the new resource.
 
-                if (FileReference* f = valueCast<FileReference>(srcValue->value.get())) {
+                if (FileReference* f = valueCast<FileReference>(srcConfigValue->value.get())) {
                     std::unique_ptr<FileReference> newFileRef;
                     if (manglePackage) {
                         newFileRef = cloneAndMangleFile(srcPackage->name, *f);
@@ -258,15 +312,15 @@
                     }
 
                     if (callback) {
-                        if (!callback(resName, srcValue->config, newFileRef.get(), f)) {
+                        if (!callback(resName, srcConfigValue->config, newFileRef.get(), f)) {
                             error = true;
                             continue;
                         }
                     }
-                    dstValue->value = std::move(newFileRef);
+                    dstConfigValue->value = std::move(newFileRef);
 
                 } else {
-                    dstValue->value = std::unique_ptr<Value>(srcValue->value->clone(
+                    dstConfigValue->value = std::unique_ptr<Value>(srcConfigValue->value->clone(
                             &mMasterTable->stringPool));
                 }
             }
@@ -277,7 +331,6 @@
 
 std::unique_ptr<FileReference> TableMerger::cloneAndMangleFile(const std::string& package,
                                                                const FileReference& fileRef) {
-
     StringPiece prefix, entry, suffix;
     if (util::extractResFilePathParts(*fileRef.path, &prefix, &entry, &suffix)) {
         std::string mangledEntry = NameMangler::mangleEntry(package, entry.toString());
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index ff3e21f..fb1cb21 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -274,4 +274,43 @@
     ASSERT_FALSE(merger.mergeOverlay({}, tableB.get()));
 }
 
+TEST_F(TableMergerTest, OverlaidStyleablesShouldBeMerged) {
+    std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
+            .setPackageId("com.app.a", 0x7f)
+            .addValue("com.app.a:styleable/Foo", test::StyleableBuilder()
+                    .addItem("com.app.a:attr/bar")
+                    .addItem("com.app.a:attr/foo", ResourceId(0x01010000))
+                    .build())
+            .build();
+
+    std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
+            .setPackageId("com.app.a", 0x7f)
+            .addValue("com.app.a:styleable/Foo", test::StyleableBuilder()
+                    .addItem("com.app.a:attr/bat")
+                    .addItem("com.app.a:attr/foo")
+                    .build())
+            .build();
+
+    ResourceTable finalTable;
+    TableMergerOptions options;
+    options.autoAddOverlay = true;
+    TableMerger merger(mContext.get(), &finalTable, options);
+
+    ASSERT_TRUE(merger.merge({}, tableA.get()));
+    ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
+
+    Debug::printTable(&finalTable, {});
+
+    Styleable* styleable = test::getValue<Styleable>(&finalTable, "com.app.a:styleable/Foo");
+    ASSERT_NE(nullptr, styleable);
+
+    std::vector<Reference> expectedRefs = {
+            Reference(test::parseNameOrDie("com.app.a:attr/bar")),
+            Reference(test::parseNameOrDie("com.app.a:attr/bat")),
+            Reference(test::parseNameOrDie("com.app.a:attr/foo"), ResourceId(0x01010000)),
+    };
+
+    EXPECT_EQ(expectedRefs, styleable->entries);
+}
+
 } // namespace aapt
diff --git a/tools/aapt2/tools/consumers/duplicates.py b/tools/aapt2/tools/consumers/duplicates.py
index c27979a..4f70b6c 100644
--- a/tools/aapt2/tools/consumers/duplicates.py
+++ b/tools/aapt2/tools/consumers/duplicates.py
@@ -37,7 +37,7 @@
         output_lines = []
         current_line = ""
         for definition in duplicates:
-            print "{0}: removing duplicate resource '{3}'".format( xml_path, definition.name)
+            print "{0}: removing duplicate resource '{1}'".format(xml_path, definition.name)
 
             if last_line_no < definition.start[0]:
                 # The next definition is on a new line, so write what we have
diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk
index 863abae..199fafa 100644
--- a/tools/split-select/Android.mk
+++ b/tools/split-select/Android.mk
@@ -51,7 +51,7 @@
     liblog \
     libcutils \
     libexpat \
-    libziparchive-host \
+    libziparchive \
     libbase
 
 cFlags := -Wall -Werror
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 7c5276c..0d68f62 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1266,6 +1266,7 @@
             }
             mTemporarilyDisabledTimestamp = source.mTemporarilyDisabledTimestamp;
             mNetworkSelectionBSSID = source.mNetworkSelectionBSSID;
+            setSeenInLastQualifiedNetworkSelection(source.getSeenInLastQualifiedNetworkSelection());
             setCandidate(source.getCandidate());
             setCandidateScore(source.getCandidateScore());
             setConnectChoice(source.getConnectChoice());