Merge "Throw exception on mismatched system vs vendor"
diff --git a/api/current.txt b/api/current.txt
index afd09ad..c10c072b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5811,6 +5811,7 @@
     method public final void setInterruptionFilter(int);
     method public void setNotificationDelegate(@NonNull String);
     method public void setNotificationPolicy(@NonNull android.app.NotificationManager.Policy);
+    method public boolean shouldHideSilentStatusBarIcons();
     method public boolean updateAutomaticZenRule(String, android.app.AutomaticZenRule);
     field public static final String ACTION_APP_BLOCK_STATE_CHANGED = "android.app.action.APP_BLOCK_STATE_CHANGED";
     field public static final String ACTION_AUTOMATIC_ZEN_RULE = "android.app.action.AUTOMATIC_ZEN_RULE";
@@ -12978,7 +12979,7 @@
     method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder removeOpenFlags(int);
     method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setCursorFactory(@Nullable android.database.sqlite.SQLiteDatabase.CursorFactory);
     method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setErrorHandler(@Nullable android.database.DatabaseErrorHandler);
-    method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setIdleConnectionTimeout(@IntRange(from=0) long);
+    method @Deprecated @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setIdleConnectionTimeout(@IntRange(from=0) long);
     method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setJournalMode(@NonNull String);
     method public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setLookasideConfig(@IntRange(from=0) int, @IntRange(from=0) int);
     method @NonNull public android.database.sqlite.SQLiteDatabase.OpenParams.Builder setOpenFlags(int);
@@ -13039,7 +13040,7 @@
     method public void onDowngrade(android.database.sqlite.SQLiteDatabase, int, int);
     method public void onOpen(android.database.sqlite.SQLiteDatabase);
     method public abstract void onUpgrade(android.database.sqlite.SQLiteDatabase, int, int);
-    method public void setIdleConnectionTimeout(@IntRange(from=0) long);
+    method @Deprecated public void setIdleConnectionTimeout(@IntRange(from=0) long);
     method public void setLookasideConfig(@IntRange(from=0) int, @IntRange(from=0) int);
     method public void setOpenParams(@NonNull android.database.sqlite.SQLiteDatabase.OpenParams);
     method public void setWriteAheadLoggingEnabled(boolean);
@@ -36527,7 +36528,7 @@
     field public static final String ACCOUNT_TYPE_LOCAL = "LOCAL";
     field public static final String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
     field public static final String ACTION_HANDLE_CUSTOM_EVENT = "android.provider.calendar.action.HANDLE_CUSTOM_EVENT";
-    field public static final String ACTION_VIEW_WORK_CALENDAR_EVENT = "android.provider.calendar.action.VIEW_WORK_CALENDAR_EVENT";
+    field public static final String ACTION_VIEW_MANAGED_PROFILE_CALENDAR_EVENT = "android.provider.calendar.action.VIEW_MANAGED_PROFILE_CALENDAR_EVENT";
     field public static final String AUTHORITY = "com.android.calendar";
     field public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
     field public static final android.net.Uri CONTENT_URI;
@@ -41555,6 +41556,7 @@
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
     method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap, int);
+    method public void onStatusBarIconsBehaviorChanged(boolean);
     method public final void requestInterruptionFilter(int);
     method public final void requestListenerHints(int);
     method public static void requestRebind(android.content.ComponentName);
@@ -52887,6 +52889,9 @@
 
   public final class UserDataRemovalRequest implements android.os.Parcelable {
     method public int describeContents();
+    method @NonNull public String getPackageName();
+    method @NonNull public java.util.List<android.view.contentcapture.UserDataRemovalRequest.UriRequest> getUriRequests();
+    method public boolean isForEverything();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.view.contentcapture.UserDataRemovalRequest> CREATOR;
   }
@@ -52898,6 +52903,11 @@
     method @NonNull public android.view.contentcapture.UserDataRemovalRequest.Builder forEverything();
   }
 
+  public final class UserDataRemovalRequest.UriRequest {
+    method @NonNull public android.net.Uri getUri();
+    method @NonNull public boolean isRecursive();
+  }
+
 }
 
 package android.view.inputmethod {
@@ -58117,13 +58127,13 @@
     ctor public ByteArrayOutputStream(int);
     method public void reset();
     method public int size();
-    method public byte[] toByteArray();
+    method @NonNull public byte[] toByteArray();
     method @NonNull public String toString(@NonNull String) throws java.io.UnsupportedEncodingException;
     method @Deprecated @NonNull public String toString(int);
     method public void write(int);
-    method public void write(byte[], int, int);
+    method public void write(@NonNull byte[], int, int);
     method public void writeTo(@NonNull java.io.OutputStream) throws java.io.IOException;
-    field protected byte[] buf;
+    field @NonNull protected byte[] buf;
     field protected int count;
   }
 
@@ -58294,12 +58304,12 @@
     method public boolean isHidden();
     method public long lastModified();
     method public long length();
-    method public String[] list();
-    method public String[] list(@Nullable java.io.FilenameFilter);
-    method public java.io.File[] listFiles();
-    method public java.io.File[] listFiles(@Nullable java.io.FilenameFilter);
-    method public java.io.File[] listFiles(@Nullable java.io.FileFilter);
-    method public static java.io.File[] listRoots();
+    method @Nullable public String[] list();
+    method @Nullable public String[] list(@Nullable java.io.FilenameFilter);
+    method @Nullable public java.io.File[] listFiles();
+    method @Nullable public java.io.File[] listFiles(@Nullable java.io.FilenameFilter);
+    method @Nullable public java.io.File[] listFiles(@Nullable java.io.FileFilter);
+    method @NonNull public static java.io.File[] listRoots();
     method public boolean mkdir();
     method public boolean mkdirs();
     method public boolean renameTo(@NonNull java.io.File);
@@ -58788,8 +58798,8 @@
     method protected void clearError();
     method public void close();
     method public void flush();
-    method @NonNull public java.io.PrintWriter format(@NonNull String, java.lang.Object...);
-    method @NonNull public java.io.PrintWriter format(@Nullable java.util.Locale, @NonNull String, java.lang.Object...);
+    method @NonNull public java.io.PrintWriter format(@NonNull String, @NonNull java.lang.Object...);
+    method @NonNull public java.io.PrintWriter format(@Nullable java.util.Locale, @NonNull String, @NonNull java.lang.Object...);
     method public void print(boolean);
     method public void print(char);
     method public void print(int);
@@ -58799,8 +58809,8 @@
     method public void print(char[]);
     method public void print(@Nullable String);
     method public void print(@Nullable Object);
-    method @NonNull public java.io.PrintWriter printf(@NonNull String, java.lang.Object...);
-    method @NonNull public java.io.PrintWriter printf(@Nullable java.util.Locale, @NonNull String, java.lang.Object...);
+    method @NonNull public java.io.PrintWriter printf(@NonNull String, @NonNull java.lang.Object...);
+    method @NonNull public java.io.PrintWriter printf(@Nullable java.util.Locale, @NonNull String, @NonNull java.lang.Object...);
     method public void println();
     method public void println(boolean);
     method public void println(char);
@@ -59626,45 +59636,45 @@
     method @NonNull public static Class<?> forName(@NonNull String) throws java.lang.ClassNotFoundException;
     method @NonNull public static Class<?> forName(@NonNull String, boolean, @Nullable ClassLoader) throws java.lang.ClassNotFoundException;
     method @Nullable public <A extends java.lang.annotation.Annotation> A getAnnotation(@NonNull Class<A>);
-    method public java.lang.annotation.Annotation[] getAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
     method @NonNull public <A extends java.lang.annotation.Annotation> A[] getAnnotationsByType(@NonNull Class<A>);
     method @Nullable public String getCanonicalName();
     method @Nullable public ClassLoader getClassLoader();
-    method public Class<?>[] getClasses();
+    method @NonNull public Class<?>[] getClasses();
     method @Nullable public Class<?> getComponentType();
-    method @NonNull public java.lang.reflect.Constructor<T> getConstructor(Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
-    method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Constructor<T> getConstructor(@Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
     method @Nullable public <A extends java.lang.annotation.Annotation> A getDeclaredAnnotation(@NonNull Class<A>);
-    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
-    method public Class<?>[] getDeclaredClasses();
-    method @NonNull public java.lang.reflect.Constructor<T> getDeclaredConstructor(Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
-    method public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
+    method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method @NonNull public Class<?>[] getDeclaredClasses();
+    method @NonNull public java.lang.reflect.Constructor<T> getDeclaredConstructor(@Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
     method @NonNull public java.lang.reflect.Field getDeclaredField(@NonNull String) throws java.lang.NoSuchFieldException;
-    method public java.lang.reflect.Field[] getDeclaredFields();
-    method @NonNull public java.lang.reflect.Method getDeclaredMethod(@NonNull String, Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
-    method public java.lang.reflect.Method[] getDeclaredMethods() throws java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Field[] getDeclaredFields();
+    method @NonNull public java.lang.reflect.Method getDeclaredMethod(@NonNull String, @Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Method[] getDeclaredMethods() throws java.lang.SecurityException;
     method @Nullable public Class<?> getDeclaringClass();
     method @Nullable public Class<?> getEnclosingClass();
     method @Nullable public java.lang.reflect.Constructor<?> getEnclosingConstructor();
     method @Nullable public java.lang.reflect.Method getEnclosingMethod();
-    method public T[] getEnumConstants();
+    method @Nullable public T[] getEnumConstants();
     method @NonNull public java.lang.reflect.Field getField(@NonNull String) throws java.lang.NoSuchFieldException;
-    method public java.lang.reflect.Field[] getFields() throws java.lang.SecurityException;
-    method public java.lang.reflect.Type[] getGenericInterfaces();
+    method @NonNull public java.lang.reflect.Field[] getFields() throws java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Type[] getGenericInterfaces();
     method @Nullable public java.lang.reflect.Type getGenericSuperclass();
-    method public Class<?>[] getInterfaces();
-    method @NonNull public java.lang.reflect.Method getMethod(@NonNull String, Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
-    method public java.lang.reflect.Method[] getMethods() throws java.lang.SecurityException;
+    method @NonNull public Class<?>[] getInterfaces();
+    method @NonNull public java.lang.reflect.Method getMethod(@NonNull String, @Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+    method @NonNull public java.lang.reflect.Method[] getMethods() throws java.lang.SecurityException;
     method public int getModifiers();
     method @NonNull public String getName();
     method @Nullable public Package getPackage();
     method @Nullable public java.security.ProtectionDomain getProtectionDomain();
     method @Nullable public java.net.URL getResource(@NonNull String);
     method @Nullable public java.io.InputStream getResourceAsStream(@NonNull String);
-    method public Object[] getSigners();
+    method @Nullable public Object[] getSigners();
     method @NonNull public String getSimpleName();
     method @Nullable public Class<? super T> getSuperclass();
-    method public java.lang.reflect.TypeVariable<java.lang.Class<T>>[] getTypeParameters();
+    method @NonNull public java.lang.reflect.TypeVariable<java.lang.Class<T>>[] getTypeParameters();
     method public boolean isAnnotation();
     method public boolean isAnonymousClass();
     method public boolean isArray();
@@ -60551,8 +60561,8 @@
     method @NonNull public static String copyValueOf(char[]);
     method public boolean endsWith(@NonNull String);
     method public boolean equalsIgnoreCase(@Nullable String);
-    method @NonNull public static String format(@NonNull String, java.lang.Object...);
-    method @NonNull public static String format(@NonNull java.util.Locale, @NonNull String, java.lang.Object...);
+    method @NonNull public static String format(@NonNull String, @NonNull java.lang.Object...);
+    method @NonNull public static String format(@NonNull java.util.Locale, @NonNull String, @NonNull java.lang.Object...);
     method @Deprecated public void getBytes(int, int, byte[], int);
     method public byte[] getBytes(@NonNull String) throws java.io.UnsupportedEncodingException;
     method public byte[] getBytes(@NonNull java.nio.charset.Charset);
@@ -60564,7 +60574,7 @@
     method public int indexOf(@NonNull String, int);
     method @NonNull public String intern();
     method public boolean isEmpty();
-    method @NonNull public static String join(@NonNull CharSequence, java.lang.CharSequence...);
+    method @NonNull public static String join(@NonNull CharSequence, @Nullable java.lang.CharSequence...);
     method @NonNull public static String join(@NonNull CharSequence, @NonNull Iterable<? extends java.lang.CharSequence>);
     method public int lastIndexOf(int);
     method public int lastIndexOf(int, int);
@@ -60579,8 +60589,8 @@
     method @NonNull public String replace(@NonNull CharSequence, @NonNull CharSequence);
     method @NonNull public String replaceAll(@NonNull String, @NonNull String);
     method @NonNull public String replaceFirst(@NonNull String, @NonNull String);
-    method public String[] split(@NonNull String, int);
-    method public String[] split(@NonNull String);
+    method @NonNull public String[] split(@NonNull String, int);
+    method @NonNull public String[] split(@NonNull String);
     method public boolean startsWith(@NonNull String, int);
     method public boolean startsWith(@NonNull String);
     method @NonNull public CharSequence subSequence(int, int);
@@ -60781,7 +60791,7 @@
     method public long getId();
     method @NonNull public final String getName();
     method public final int getPriority();
-    method public StackTraceElement[] getStackTrace();
+    method @NonNull public StackTraceElement[] getStackTrace();
     method @NonNull public java.lang.Thread.State getState();
     method @Nullable public final ThreadGroup getThreadGroup();
     method @Nullable public java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionHandler();
@@ -60879,13 +60889,13 @@
     method @Nullable public Throwable getCause();
     method @Nullable public String getLocalizedMessage();
     method @Nullable public String getMessage();
-    method public StackTraceElement[] getStackTrace();
-    method public final Throwable[] getSuppressed();
+    method @NonNull public StackTraceElement[] getStackTrace();
+    method @NonNull public final Throwable[] getSuppressed();
     method @NonNull public Throwable initCause(@Nullable Throwable);
     method public void printStackTrace();
     method public void printStackTrace(@NonNull java.io.PrintStream);
     method public void printStackTrace(@NonNull java.io.PrintWriter);
-    method public void setStackTrace(StackTraceElement[]);
+    method public void setStackTrace(@NonNull StackTraceElement[]);
   }
 
   public class TypeNotPresentException extends java.lang.RuntimeException {
@@ -61208,8 +61218,8 @@
   public class AccessibleObject implements java.lang.reflect.AnnotatedElement {
     ctor protected AccessibleObject();
     method @Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@NonNull Class<T>);
-    method public java.lang.annotation.Annotation[] getAnnotations();
-    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public boolean isAccessible();
     method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean) throws java.lang.SecurityException;
     method public void setAccessible(boolean) throws java.lang.SecurityException;
@@ -61217,10 +61227,10 @@
 
   public interface AnnotatedElement {
     method @Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@NonNull Class<T>);
-    method public java.lang.annotation.Annotation[] getAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
     method public default <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(@NonNull Class<T>);
     method @Nullable public default <T extends java.lang.annotation.Annotation> T getDeclaredAnnotation(@NonNull Class<T>);
-    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method public default <T extends java.lang.annotation.Annotation> T[] getDeclaredAnnotationsByType(@NonNull Class<T>);
     method public default boolean isAnnotationPresent(@NonNull Class<? extends java.lang.annotation.Annotation>);
   }
@@ -61255,20 +61265,20 @@
     method public int getModifiers();
     method @NonNull public String getName();
     method public java.lang.annotation.Annotation[][] getParameterAnnotations();
-    method public Class<?>[] getParameterTypes();
+    method @NonNull public Class<?>[] getParameterTypes();
     method public java.lang.reflect.TypeVariable<java.lang.reflect.Constructor<T>>[] getTypeParameters();
     method @NonNull public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
     method @NonNull public String toGenericString();
   }
 
   public abstract class Executable extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
-    method public abstract Class<?>[] getExceptionTypes();
-    method public java.lang.reflect.Type[] getGenericExceptionTypes();
-    method public java.lang.reflect.Type[] getGenericParameterTypes();
-    method public abstract java.lang.annotation.Annotation[][] getParameterAnnotations();
+    method @NonNull public abstract Class<?>[] getExceptionTypes();
+    method @NonNull public java.lang.reflect.Type[] getGenericExceptionTypes();
+    method @NonNull public java.lang.reflect.Type[] getGenericParameterTypes();
+    method @NonNull public abstract java.lang.annotation.Annotation[][] getParameterAnnotations();
     method public int getParameterCount();
-    method public abstract Class<?>[] getParameterTypes();
-    method public java.lang.reflect.Parameter[] getParameters();
+    method @NonNull public abstract Class<?>[] getParameterTypes();
+    method @NonNull public java.lang.reflect.Parameter[] getParameters();
     method public final boolean isAnnotationPresent(@NonNull Class<? extends java.lang.annotation.Annotation>);
     method public boolean isSynthetic();
     method public boolean isVarArgs();
@@ -61357,7 +61367,7 @@
     method @NonNull public Class<?>[] getParameterTypes();
     method @NonNull public Class<?> getReturnType();
     method @NonNull public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
-    method @Nullable public Object invoke(@Nullable Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
+    method @Nullable public Object invoke(@Nullable Object, @Nullable java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
     method public boolean isBridge();
     method public boolean isDefault();
     method @NonNull public String toGenericString();
@@ -61400,8 +61410,8 @@
 
   public final class Parameter implements java.lang.reflect.AnnotatedElement {
     method @Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@NonNull Class<T>);
-    method public java.lang.annotation.Annotation[] getAnnotations();
-    method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
+    method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
     method @NonNull public java.lang.reflect.Executable getDeclaringExecutable();
     method public int getModifiers();
     method @NonNull public String getName();
@@ -61414,7 +61424,7 @@
   }
 
   public interface ParameterizedType extends java.lang.reflect.Type {
-    method public java.lang.reflect.Type[] getActualTypeArguments();
+    method @NonNull public java.lang.reflect.Type[] getActualTypeArguments();
     method @Nullable public java.lang.reflect.Type getOwnerType();
     method @NonNull public java.lang.reflect.Type getRawType();
   }
@@ -61422,9 +61432,9 @@
   public class Proxy implements java.io.Serializable {
     ctor protected Proxy(@NonNull java.lang.reflect.InvocationHandler);
     method @NonNull public static java.lang.reflect.InvocationHandler getInvocationHandler(@NonNull Object) throws java.lang.IllegalArgumentException;
-    method @NonNull public static Class<?> getProxyClass(@Nullable ClassLoader, Class<?>...) throws java.lang.IllegalArgumentException;
+    method @NonNull public static Class<?> getProxyClass(@Nullable ClassLoader, @NonNull Class<?>...) throws java.lang.IllegalArgumentException;
     method public static boolean isProxyClass(@NonNull Class<?>);
-    method @NonNull public static Object newProxyInstance(@Nullable ClassLoader, Class<?>[], @NonNull java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentException;
+    method @NonNull public static Object newProxyInstance(@Nullable ClassLoader, @NonNull Class<?>[], @NonNull java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentException;
     field protected java.lang.reflect.InvocationHandler h;
   }
 
@@ -61438,7 +61448,7 @@
   }
 
   public interface TypeVariable<D extends java.lang.reflect.GenericDeclaration> extends java.lang.reflect.Type {
-    method public java.lang.reflect.Type[] getBounds();
+    method @NonNull public java.lang.reflect.Type[] getBounds();
     method @NonNull public D getGenericDeclaration();
     method @NonNull public String getName();
   }
@@ -61450,8 +61460,8 @@
   }
 
   public interface WildcardType extends java.lang.reflect.Type {
-    method public java.lang.reflect.Type[] getLowerBounds();
-    method public java.lang.reflect.Type[] getUpperBounds();
+    method @NonNull public java.lang.reflect.Type[] getLowerBounds();
+    method @NonNull public java.lang.reflect.Type[] getUpperBounds();
   }
 
 }
@@ -62495,7 +62505,7 @@
   public abstract class ByteBuffer extends java.nio.Buffer implements java.lang.Comparable<java.nio.ByteBuffer> {
     method @NonNull public static java.nio.ByteBuffer allocate(int);
     method @NonNull public static java.nio.ByteBuffer allocateDirect(int);
-    method public final byte[] array();
+    method @NonNull public final byte[] array();
     method public final int arrayOffset();
     method @NonNull public abstract java.nio.CharBuffer asCharBuffer();
     method @NonNull public abstract java.nio.DoubleBuffer asDoubleBuffer();
@@ -62509,8 +62519,8 @@
     method @NonNull public abstract java.nio.ByteBuffer duplicate();
     method public abstract byte get();
     method public abstract byte get(int);
-    method @NonNull public java.nio.ByteBuffer get(byte[], int, int);
-    method @NonNull public java.nio.ByteBuffer get(byte[]);
+    method @NonNull public java.nio.ByteBuffer get(@NonNull byte[], int, int);
+    method @NonNull public java.nio.ByteBuffer get(@NonNull byte[]);
     method public abstract char getChar();
     method public abstract char getChar(int);
     method public abstract double getDouble();
@@ -62529,8 +62539,8 @@
     method @NonNull public abstract java.nio.ByteBuffer put(byte);
     method @NonNull public abstract java.nio.ByteBuffer put(int, byte);
     method @NonNull public java.nio.ByteBuffer put(@NonNull java.nio.ByteBuffer);
-    method @NonNull public java.nio.ByteBuffer put(byte[], int, int);
-    method @NonNull public final java.nio.ByteBuffer put(byte[]);
+    method @NonNull public java.nio.ByteBuffer put(@NonNull byte[], int, int);
+    method @NonNull public final java.nio.ByteBuffer put(@NonNull byte[]);
     method @NonNull public abstract java.nio.ByteBuffer putChar(char);
     method @NonNull public abstract java.nio.ByteBuffer putChar(int, char);
     method @NonNull public abstract java.nio.ByteBuffer putDouble(double);
@@ -62544,8 +62554,8 @@
     method @NonNull public abstract java.nio.ByteBuffer putShort(short);
     method @NonNull public abstract java.nio.ByteBuffer putShort(int, short);
     method @NonNull public abstract java.nio.ByteBuffer slice();
-    method @NonNull public static java.nio.ByteBuffer wrap(byte[], int, int);
-    method @NonNull public static java.nio.ByteBuffer wrap(byte[]);
+    method @NonNull public static java.nio.ByteBuffer wrap(@NonNull byte[], int, int);
+    method @NonNull public static java.nio.ByteBuffer wrap(@NonNull byte[]);
   }
 
   public final class ByteOrder {
@@ -64378,20 +64388,20 @@
 
   public abstract class MessageDigest extends java.security.MessageDigestSpi {
     ctor protected MessageDigest(@NonNull String);
-    method public byte[] digest();
-    method public int digest(byte[], int, int) throws java.security.DigestException;
-    method public byte[] digest(byte[]);
+    method @NonNull public byte[] digest();
+    method public int digest(@NonNull byte[], int, int) throws java.security.DigestException;
+    method @NonNull public byte[] digest(@NonNull byte[]);
     method @NonNull public final String getAlgorithm();
     method public final int getDigestLength();
     method @NonNull public static java.security.MessageDigest getInstance(@NonNull String) throws java.security.NoSuchAlgorithmException;
     method @NonNull public static java.security.MessageDigest getInstance(@NonNull String, @NonNull String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
     method @NonNull public static java.security.MessageDigest getInstance(@NonNull String, @NonNull java.security.Provider) throws java.security.NoSuchAlgorithmException;
     method @NonNull public final java.security.Provider getProvider();
-    method public static boolean isEqual(byte[], byte[]);
+    method public static boolean isEqual(@Nullable byte[], @Nullable byte[]);
     method public void reset();
     method public void update(byte);
-    method public void update(byte[], int, int);
-    method public void update(byte[]);
+    method public void update(@NonNull byte[], int, int);
+    method public void update(@NonNull byte[]);
     method public final void update(@NonNull java.nio.ByteBuffer);
   }
 
@@ -66998,7 +67008,7 @@
     method @NonNull public final StringBuffer format(@NonNull Object, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
     method @NonNull public abstract StringBuffer format(@NonNull java.util.Date, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
     method @NonNull public final String format(@NonNull java.util.Date);
-    method public static java.util.Locale[] getAvailableLocales();
+    method @NonNull public static java.util.Locale[] getAvailableLocales();
     method @NonNull public java.util.Calendar getCalendar();
     method @NonNull public static final java.text.DateFormat getDateInstance();
     method @NonNull public static final java.text.DateFormat getDateInstance(int);
@@ -67238,7 +67248,7 @@
     method @NonNull public final String format(long);
     method @NonNull public abstract StringBuffer format(double, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
     method @NonNull public abstract StringBuffer format(long, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
-    method public static java.util.Locale[] getAvailableLocales();
+    method @NonNull public static java.util.Locale[] getAvailableLocales();
     method @Nullable public java.util.Currency getCurrency();
     method @NonNull public static final java.text.NumberFormat getCurrencyInstance();
     method @NonNull public static java.text.NumberFormat getCurrencyInstance(@NonNull java.util.Locale);
@@ -68892,8 +68902,8 @@
     method public boolean remove(@Nullable Object);
     method public boolean removeAll(@NonNull java.util.Collection<?>);
     method public boolean retainAll(@NonNull java.util.Collection<?>);
-    method public Object[] toArray();
-    method public <T> T[] toArray(T[]);
+    method @NonNull public Object[] toArray();
+    method @NonNull public <T> T[] toArray(@NonNull T[]);
   }
 
   public abstract class AbstractList<E> extends java.util.AbstractCollection<E> implements java.util.List<E> {
@@ -69002,161 +69012,161 @@
   }
 
   public class Arrays {
-    method @NonNull @java.lang.SafeVarargs public static <T> java.util.List<T> asList(T...);
-    method public static int binarySearch(long[], long);
-    method public static int binarySearch(long[], int, int, long);
-    method public static int binarySearch(int[], int);
-    method public static int binarySearch(int[], int, int, int);
-    method public static int binarySearch(short[], short);
-    method public static int binarySearch(short[], int, int, short);
-    method public static int binarySearch(char[], char);
-    method public static int binarySearch(char[], int, int, char);
-    method public static int binarySearch(byte[], byte);
-    method public static int binarySearch(byte[], int, int, byte);
-    method public static int binarySearch(double[], double);
-    method public static int binarySearch(double[], int, int, double);
-    method public static int binarySearch(float[], float);
-    method public static int binarySearch(float[], int, int, float);
-    method public static int binarySearch(Object[], @NonNull Object);
-    method public static int binarySearch(Object[], int, int, @NonNull Object);
-    method public static <T> int binarySearch(T[], T, @Nullable java.util.Comparator<? super T>);
-    method public static <T> int binarySearch(T[], int, int, T, @Nullable java.util.Comparator<? super T>);
-    method public static <T> T[] copyOf(T[], int);
-    method public static <T, U> T[] copyOf(U[], int, @NonNull Class<? extends T[]>);
-    method public static byte[] copyOf(byte[], int);
-    method public static short[] copyOf(short[], int);
-    method public static int[] copyOf(int[], int);
-    method public static long[] copyOf(long[], int);
-    method public static char[] copyOf(char[], int);
-    method public static float[] copyOf(float[], int);
-    method public static double[] copyOf(double[], int);
-    method public static boolean[] copyOf(boolean[], int);
-    method public static <T> T[] copyOfRange(T[], int, int);
-    method public static <T, U> T[] copyOfRange(U[], int, int, @NonNull Class<? extends T[]>);
-    method public static byte[] copyOfRange(byte[], int, int);
-    method public static short[] copyOfRange(short[], int, int);
-    method public static int[] copyOfRange(int[], int, int);
-    method public static long[] copyOfRange(long[], int, int);
-    method public static char[] copyOfRange(char[], int, int);
-    method public static float[] copyOfRange(float[], int, int);
-    method public static double[] copyOfRange(double[], int, int);
-    method public static boolean[] copyOfRange(boolean[], int, int);
-    method public static boolean deepEquals(Object[], Object[]);
-    method public static int deepHashCode(Object[]);
-    method @NonNull public static String deepToString(Object[]);
-    method public static boolean equals(long[], long[]);
-    method public static boolean equals(int[], int[]);
-    method public static boolean equals(short[], short[]);
-    method public static boolean equals(char[], char[]);
-    method public static boolean equals(byte[], byte[]);
-    method public static boolean equals(boolean[], boolean[]);
-    method public static boolean equals(double[], double[]);
-    method public static boolean equals(float[], float[]);
-    method public static boolean equals(Object[], Object[]);
-    method public static void fill(long[], long);
-    method public static void fill(long[], int, int, long);
-    method public static void fill(int[], int);
-    method public static void fill(int[], int, int, int);
-    method public static void fill(short[], short);
-    method public static void fill(short[], int, int, short);
-    method public static void fill(char[], char);
-    method public static void fill(char[], int, int, char);
-    method public static void fill(byte[], byte);
-    method public static void fill(byte[], int, int, byte);
-    method public static void fill(boolean[], boolean);
-    method public static void fill(boolean[], int, int, boolean);
-    method public static void fill(double[], double);
-    method public static void fill(double[], int, int, double);
-    method public static void fill(float[], float);
-    method public static void fill(float[], int, int, float);
-    method public static void fill(Object[], @Nullable Object);
-    method public static void fill(Object[], int, int, @Nullable Object);
-    method public static int hashCode(long[]);
-    method public static int hashCode(int[]);
-    method public static int hashCode(short[]);
-    method public static int hashCode(char[]);
-    method public static int hashCode(byte[]);
-    method public static int hashCode(boolean[]);
-    method public static int hashCode(float[]);
-    method public static int hashCode(double[]);
-    method public static int hashCode(Object[]);
-    method public static <T> void parallelPrefix(T[], @NonNull java.util.function.BinaryOperator<T>);
-    method public static <T> void parallelPrefix(T[], int, int, @NonNull java.util.function.BinaryOperator<T>);
-    method public static void parallelPrefix(long[], @NonNull java.util.function.LongBinaryOperator);
-    method public static void parallelPrefix(long[], int, int, @NonNull java.util.function.LongBinaryOperator);
-    method public static void parallelPrefix(double[], @NonNull java.util.function.DoubleBinaryOperator);
-    method public static void parallelPrefix(double[], int, int, @NonNull java.util.function.DoubleBinaryOperator);
-    method public static void parallelPrefix(int[], @NonNull java.util.function.IntBinaryOperator);
-    method public static void parallelPrefix(int[], int, int, @NonNull java.util.function.IntBinaryOperator);
-    method public static <T> void parallelSetAll(T[], @NonNull java.util.function.IntFunction<? extends T>);
-    method public static void parallelSetAll(int[], @NonNull java.util.function.IntUnaryOperator);
-    method public static void parallelSetAll(long[], @NonNull java.util.function.IntToLongFunction);
-    method public static void parallelSetAll(double[], @NonNull java.util.function.IntToDoubleFunction);
-    method public static void parallelSort(byte[]);
-    method public static void parallelSort(byte[], int, int);
-    method public static void parallelSort(char[]);
-    method public static void parallelSort(char[], int, int);
-    method public static void parallelSort(short[]);
-    method public static void parallelSort(short[], int, int);
-    method public static void parallelSort(int[]);
-    method public static void parallelSort(int[], int, int);
-    method public static void parallelSort(long[]);
-    method public static void parallelSort(long[], int, int);
-    method public static void parallelSort(float[]);
-    method public static void parallelSort(float[], int, int);
-    method public static void parallelSort(double[]);
-    method public static void parallelSort(double[], int, int);
-    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[]);
-    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[], int, int);
-    method public static <T> void parallelSort(T[], @Nullable java.util.Comparator<? super T>);
-    method public static <T> void parallelSort(T[], int, int, @Nullable java.util.Comparator<? super T>);
-    method public static <T> void setAll(T[], @NonNull java.util.function.IntFunction<? extends T>);
-    method public static void setAll(int[], @NonNull java.util.function.IntUnaryOperator);
-    method public static void setAll(long[], @NonNull java.util.function.IntToLongFunction);
-    method public static void setAll(double[], @NonNull java.util.function.IntToDoubleFunction);
-    method public static void sort(int[]);
-    method public static void sort(int[], int, int);
-    method public static void sort(long[]);
-    method public static void sort(long[], int, int);
-    method public static void sort(short[]);
-    method public static void sort(short[], int, int);
-    method public static void sort(char[]);
-    method public static void sort(char[], int, int);
-    method public static void sort(byte[]);
-    method public static void sort(byte[], int, int);
-    method public static void sort(float[]);
-    method public static void sort(float[], int, int);
-    method public static void sort(double[]);
-    method public static void sort(double[], int, int);
-    method public static void sort(Object[]);
-    method public static void sort(Object[], int, int);
-    method public static <T> void sort(T[], @Nullable java.util.Comparator<? super T>);
-    method public static <T> void sort(T[], int, int, @Nullable java.util.Comparator<? super T>);
-    method @NonNull public static <T> java.util.Spliterator<T> spliterator(T[]);
-    method @NonNull public static <T> java.util.Spliterator<T> spliterator(T[], int, int);
-    method @NonNull public static java.util.Spliterator.OfInt spliterator(int[]);
-    method @NonNull public static java.util.Spliterator.OfInt spliterator(int[], int, int);
-    method @NonNull public static java.util.Spliterator.OfLong spliterator(long[]);
-    method @NonNull public static java.util.Spliterator.OfLong spliterator(long[], int, int);
-    method @NonNull public static java.util.Spliterator.OfDouble spliterator(double[]);
-    method @NonNull public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
-    method @NonNull public static <T> java.util.stream.Stream<T> stream(T[]);
-    method @NonNull public static <T> java.util.stream.Stream<T> stream(T[], int, int);
-    method @NonNull public static java.util.stream.IntStream stream(int[]);
-    method @NonNull public static java.util.stream.IntStream stream(int[], int, int);
-    method @NonNull public static java.util.stream.LongStream stream(long[]);
-    method @NonNull public static java.util.stream.LongStream stream(long[], int, int);
-    method @NonNull public static java.util.stream.DoubleStream stream(double[]);
-    method @NonNull public static java.util.stream.DoubleStream stream(double[], int, int);
-    method @NonNull public static String toString(long[]);
-    method @NonNull public static String toString(int[]);
-    method @NonNull public static String toString(short[]);
-    method @NonNull public static String toString(char[]);
-    method @NonNull public static String toString(byte[]);
-    method @NonNull public static String toString(boolean[]);
-    method @NonNull public static String toString(float[]);
-    method @NonNull public static String toString(double[]);
-    method @NonNull public static String toString(Object[]);
+    method @NonNull @java.lang.SafeVarargs public static <T> java.util.List<T> asList(@NonNull T...);
+    method public static int binarySearch(@NonNull long[], long);
+    method public static int binarySearch(@NonNull long[], int, int, long);
+    method public static int binarySearch(@NonNull int[], int);
+    method public static int binarySearch(@NonNull int[], int, int, int);
+    method public static int binarySearch(@NonNull short[], short);
+    method public static int binarySearch(@NonNull short[], int, int, short);
+    method public static int binarySearch(@NonNull char[], char);
+    method public static int binarySearch(@NonNull char[], int, int, char);
+    method public static int binarySearch(@NonNull byte[], byte);
+    method public static int binarySearch(@NonNull byte[], int, int, byte);
+    method public static int binarySearch(@NonNull double[], double);
+    method public static int binarySearch(@NonNull double[], int, int, double);
+    method public static int binarySearch(@NonNull float[], float);
+    method public static int binarySearch(@NonNull float[], int, int, float);
+    method public static int binarySearch(@NonNull Object[], @NonNull Object);
+    method public static int binarySearch(@NonNull Object[], int, int, @NonNull Object);
+    method public static <T> int binarySearch(@NonNull T[], T, @Nullable java.util.Comparator<? super T>);
+    method public static <T> int binarySearch(@NonNull T[], int, int, T, @Nullable java.util.Comparator<? super T>);
+    method @NonNull public static <T> T[] copyOf(@NonNull T[], int);
+    method @NonNull public static <T, U> T[] copyOf(@NonNull U[], int, @NonNull Class<? extends T[]>);
+    method @NonNull public static byte[] copyOf(@NonNull byte[], int);
+    method @NonNull public static short[] copyOf(@NonNull short[], int);
+    method @NonNull public static int[] copyOf(@NonNull int[], int);
+    method @NonNull public static long[] copyOf(@NonNull long[], int);
+    method @NonNull public static char[] copyOf(@NonNull char[], int);
+    method @NonNull public static float[] copyOf(@NonNull float[], int);
+    method @NonNull public static double[] copyOf(@NonNull double[], int);
+    method @NonNull public static boolean[] copyOf(@NonNull boolean[], int);
+    method @NonNull public static <T> T[] copyOfRange(@NonNull T[], int, int);
+    method @NonNull public static <T, U> T[] copyOfRange(@NonNull U[], int, int, @NonNull Class<? extends T[]>);
+    method @NonNull public static byte[] copyOfRange(@NonNull byte[], int, int);
+    method @NonNull public static short[] copyOfRange(@NonNull short[], int, int);
+    method @NonNull public static int[] copyOfRange(@NonNull int[], int, int);
+    method @NonNull public static long[] copyOfRange(@NonNull long[], int, int);
+    method @NonNull public static char[] copyOfRange(@NonNull char[], int, int);
+    method @NonNull public static float[] copyOfRange(@NonNull float[], int, int);
+    method @NonNull public static double[] copyOfRange(@NonNull double[], int, int);
+    method @NonNull public static boolean[] copyOfRange(@NonNull boolean[], int, int);
+    method public static boolean deepEquals(@Nullable Object[], @Nullable Object[]);
+    method public static int deepHashCode(@Nullable Object[]);
+    method @NonNull public static String deepToString(@Nullable Object[]);
+    method public static boolean equals(@Nullable long[], @Nullable long[]);
+    method public static boolean equals(@Nullable int[], @Nullable int[]);
+    method public static boolean equals(@Nullable short[], @Nullable short[]);
+    method public static boolean equals(@Nullable char[], @Nullable char[]);
+    method public static boolean equals(@Nullable byte[], @Nullable byte[]);
+    method public static boolean equals(@Nullable boolean[], @Nullable boolean[]);
+    method public static boolean equals(@Nullable double[], @Nullable double[]);
+    method public static boolean equals(@Nullable float[], @Nullable float[]);
+    method public static boolean equals(@Nullable Object[], @Nullable Object[]);
+    method public static void fill(@NonNull long[], long);
+    method public static void fill(@NonNull long[], int, int, long);
+    method public static void fill(@NonNull int[], int);
+    method public static void fill(@NonNull int[], int, int, int);
+    method public static void fill(@NonNull short[], short);
+    method public static void fill(@NonNull short[], int, int, short);
+    method public static void fill(@NonNull char[], char);
+    method public static void fill(@NonNull char[], int, int, char);
+    method public static void fill(@NonNull byte[], byte);
+    method public static void fill(@NonNull byte[], int, int, byte);
+    method public static void fill(@NonNull boolean[], boolean);
+    method public static void fill(@NonNull boolean[], int, int, boolean);
+    method public static void fill(@NonNull double[], double);
+    method public static void fill(@NonNull double[], int, int, double);
+    method public static void fill(@NonNull float[], float);
+    method public static void fill(@NonNull float[], int, int, float);
+    method public static void fill(@NonNull Object[], @Nullable Object);
+    method public static void fill(@NonNull Object[], int, int, @Nullable Object);
+    method public static int hashCode(@Nullable long[]);
+    method public static int hashCode(@Nullable int[]);
+    method public static int hashCode(@Nullable short[]);
+    method public static int hashCode(@Nullable char[]);
+    method public static int hashCode(@Nullable byte[]);
+    method public static int hashCode(@Nullable boolean[]);
+    method public static int hashCode(@Nullable float[]);
+    method public static int hashCode(@Nullable double[]);
+    method public static int hashCode(@Nullable Object[]);
+    method public static <T> void parallelPrefix(@NonNull T[], @NonNull java.util.function.BinaryOperator<T>);
+    method public static <T> void parallelPrefix(@NonNull T[], int, int, @NonNull java.util.function.BinaryOperator<T>);
+    method public static void parallelPrefix(@NonNull long[], @NonNull java.util.function.LongBinaryOperator);
+    method public static void parallelPrefix(@NonNull long[], int, int, @NonNull java.util.function.LongBinaryOperator);
+    method public static void parallelPrefix(@NonNull double[], @NonNull java.util.function.DoubleBinaryOperator);
+    method public static void parallelPrefix(@NonNull double[], int, int, @NonNull java.util.function.DoubleBinaryOperator);
+    method public static void parallelPrefix(@NonNull int[], @NonNull java.util.function.IntBinaryOperator);
+    method public static void parallelPrefix(@NonNull int[], int, int, @NonNull java.util.function.IntBinaryOperator);
+    method public static <T> void parallelSetAll(@NonNull T[], @NonNull java.util.function.IntFunction<? extends T>);
+    method public static void parallelSetAll(@NonNull int[], @NonNull java.util.function.IntUnaryOperator);
+    method public static void parallelSetAll(@NonNull long[], @NonNull java.util.function.IntToLongFunction);
+    method public static void parallelSetAll(@NonNull double[], @NonNull java.util.function.IntToDoubleFunction);
+    method public static void parallelSort(@NonNull byte[]);
+    method public static void parallelSort(@NonNull byte[], int, int);
+    method public static void parallelSort(@NonNull char[]);
+    method public static void parallelSort(@NonNull char[], int, int);
+    method public static void parallelSort(@NonNull short[]);
+    method public static void parallelSort(@NonNull short[], int, int);
+    method public static void parallelSort(@NonNull int[]);
+    method public static void parallelSort(@NonNull int[], int, int);
+    method public static void parallelSort(@NonNull long[]);
+    method public static void parallelSort(@NonNull long[], int, int);
+    method public static void parallelSort(@NonNull float[]);
+    method public static void parallelSort(@NonNull float[], int, int);
+    method public static void parallelSort(@NonNull double[]);
+    method public static void parallelSort(@NonNull double[], int, int);
+    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(@NonNull T[]);
+    method public static <T extends java.lang.Comparable<? super T>> void parallelSort(@NonNull T[], int, int);
+    method public static <T> void parallelSort(@NonNull T[], @Nullable java.util.Comparator<? super T>);
+    method public static <T> void parallelSort(@NonNull T[], int, int, @Nullable java.util.Comparator<? super T>);
+    method public static <T> void setAll(@NonNull T[], @NonNull java.util.function.IntFunction<? extends T>);
+    method public static void setAll(@NonNull int[], @NonNull java.util.function.IntUnaryOperator);
+    method public static void setAll(@NonNull long[], @NonNull java.util.function.IntToLongFunction);
+    method public static void setAll(@NonNull double[], @NonNull java.util.function.IntToDoubleFunction);
+    method public static void sort(@NonNull int[]);
+    method public static void sort(@NonNull int[], int, int);
+    method public static void sort(@NonNull long[]);
+    method public static void sort(@NonNull long[], int, int);
+    method public static void sort(@NonNull short[]);
+    method public static void sort(@NonNull short[], int, int);
+    method public static void sort(@NonNull char[]);
+    method public static void sort(@NonNull char[], int, int);
+    method public static void sort(@NonNull byte[]);
+    method public static void sort(@NonNull byte[], int, int);
+    method public static void sort(@NonNull float[]);
+    method public static void sort(@NonNull float[], int, int);
+    method public static void sort(@NonNull double[]);
+    method public static void sort(@NonNull double[], int, int);
+    method public static void sort(@NonNull Object[]);
+    method public static void sort(@NonNull Object[], int, int);
+    method public static <T> void sort(@NonNull T[], @Nullable java.util.Comparator<? super T>);
+    method public static <T> void sort(@NonNull T[], int, int, @Nullable java.util.Comparator<? super T>);
+    method @NonNull public static <T> java.util.Spliterator<T> spliterator(@NonNull T[]);
+    method @NonNull public static <T> java.util.Spliterator<T> spliterator(@NonNull T[], int, int);
+    method @NonNull public static java.util.Spliterator.OfInt spliterator(@NonNull int[]);
+    method @NonNull public static java.util.Spliterator.OfInt spliterator(@NonNull int[], int, int);
+    method @NonNull public static java.util.Spliterator.OfLong spliterator(@NonNull long[]);
+    method @NonNull public static java.util.Spliterator.OfLong spliterator(@NonNull long[], int, int);
+    method @NonNull public static java.util.Spliterator.OfDouble spliterator(@NonNull double[]);
+    method @NonNull public static java.util.Spliterator.OfDouble spliterator(@NonNull double[], int, int);
+    method @NonNull public static <T> java.util.stream.Stream<T> stream(@NonNull T[]);
+    method @NonNull public static <T> java.util.stream.Stream<T> stream(@NonNull T[], int, int);
+    method @NonNull public static java.util.stream.IntStream stream(@NonNull int[]);
+    method @NonNull public static java.util.stream.IntStream stream(@NonNull int[], int, int);
+    method @NonNull public static java.util.stream.LongStream stream(@NonNull long[]);
+    method @NonNull public static java.util.stream.LongStream stream(@NonNull long[], int, int);
+    method @NonNull public static java.util.stream.DoubleStream stream(@NonNull double[]);
+    method @NonNull public static java.util.stream.DoubleStream stream(@NonNull double[], int, int);
+    method @NonNull public static String toString(@Nullable long[]);
+    method @NonNull public static String toString(@Nullable int[]);
+    method @NonNull public static String toString(@Nullable short[]);
+    method @NonNull public static String toString(@Nullable char[]);
+    method @NonNull public static String toString(@Nullable byte[]);
+    method @NonNull public static String toString(@Nullable boolean[]);
+    method @NonNull public static String toString(@Nullable float[]);
+    method @NonNull public static String toString(@Nullable double[]);
+    method @NonNull public static String toString(@Nullable Object[]);
   }
 
   public class Base64 {
@@ -69240,7 +69250,7 @@
     method public int getActualMaximum(int);
     method public int getActualMinimum(int);
     method @NonNull public static java.util.Set<java.lang.String> getAvailableCalendarTypes();
-    method public static java.util.Locale[] getAvailableLocales();
+    method @NonNull public static java.util.Locale[] getAvailableLocales();
     method @NonNull public String getCalendarType();
     method @Nullable public String getDisplayName(int, int, @NonNull java.util.Locale);
     method @Nullable public java.util.Map<java.lang.String,java.lang.Integer> getDisplayNames(int, int, @NonNull java.util.Locale);
@@ -69328,8 +69338,8 @@
     field public static final int YEAR = 1; // 0x1
     field public static final int ZONE_OFFSET = 15; // 0xf
     field protected boolean areFieldsSet;
-    field protected int[] fields;
-    field protected boolean[] isSet;
+    field @NonNull protected int[] fields;
+    field @NonNull protected boolean[] isSet;
     field protected boolean isTimeSet;
     field protected long time;
   }
@@ -69340,7 +69350,7 @@
     method @NonNull public java.util.Calendar.Builder set(int, int);
     method @NonNull public java.util.Calendar.Builder setCalendarType(@NonNull String);
     method @NonNull public java.util.Calendar.Builder setDate(int, int, int);
-    method @NonNull public java.util.Calendar.Builder setFields(int...);
+    method @NonNull public java.util.Calendar.Builder setFields(@NonNull int...);
     method @NonNull public java.util.Calendar.Builder setInstant(long);
     method @NonNull public java.util.Calendar.Builder setInstant(@NonNull java.util.Date);
     method @NonNull public java.util.Calendar.Builder setLenient(boolean);
@@ -69370,12 +69380,12 @@
     method public int size();
     method @NonNull public default java.util.Spliterator<E> spliterator();
     method @NonNull public default java.util.stream.Stream<E> stream();
-    method public Object[] toArray();
-    method public <T> T[] toArray(T[]);
+    method @NonNull public Object[] toArray();
+    method @NonNull public <T> T[] toArray(@NonNull T[]);
   }
 
   public class Collections {
-    method @java.lang.SafeVarargs public static <T> boolean addAll(@NonNull java.util.Collection<? super T>, T...);
+    method @java.lang.SafeVarargs public static <T> boolean addAll(@NonNull java.util.Collection<? super T>, @NonNull T...);
     method @NonNull public static <T> java.util.Queue<T> asLifoQueue(@NonNull java.util.Deque<T>);
     method public static <T> int binarySearch(@NonNull java.util.List<? extends java.lang.Comparable<? super T>>, @NonNull T);
     method public static <T> int binarySearch(@NonNull java.util.List<? extends T>, T, @Nullable java.util.Comparator<? super T>);
@@ -69893,7 +69903,7 @@
     method @NonNull public static java.util.List<java.lang.String> filterTags(@NonNull java.util.List<java.util.Locale.LanguageRange>, @NonNull java.util.Collection<java.lang.String>, @NonNull java.util.Locale.FilteringMode);
     method @NonNull public static java.util.List<java.lang.String> filterTags(@NonNull java.util.List<java.util.Locale.LanguageRange>, @NonNull java.util.Collection<java.lang.String>);
     method @NonNull public static java.util.Locale forLanguageTag(@NonNull String);
-    method public static java.util.Locale[] getAvailableLocales();
+    method @NonNull public static java.util.Locale[] getAvailableLocales();
     method @NonNull public String getCountry();
     method @NonNull public static java.util.Locale getDefault();
     method @NonNull public static java.util.Locale getDefault(@NonNull java.util.Locale.Category);
@@ -69911,8 +69921,8 @@
     method @NonNull public java.util.Set<java.lang.Character> getExtensionKeys();
     method @NonNull public String getISO3Country() throws java.util.MissingResourceException;
     method @NonNull public String getISO3Language() throws java.util.MissingResourceException;
-    method public static String[] getISOCountries();
-    method public static String[] getISOLanguages();
+    method @NonNull public static String[] getISOCountries();
+    method @NonNull public static String[] getISOLanguages();
     method @NonNull public String getLanguage();
     method @NonNull public String getScript();
     method @NonNull public java.util.Set<java.lang.String> getUnicodeLocaleAttributes();
@@ -70106,7 +70116,7 @@
     method public static <T> int compare(T, T, @NonNull java.util.Comparator<? super T>);
     method public static boolean deepEquals(@Nullable Object, @Nullable Object);
     method public static boolean equals(@Nullable Object, @Nullable Object);
-    method public static int hash(java.lang.Object...);
+    method public static int hash(@Nullable java.lang.Object...);
     method public static int hashCode(@Nullable Object);
     method public static boolean isNull(@Nullable Object);
     method public static boolean nonNull(@Nullable Object);
@@ -70771,7 +70781,7 @@
     method public void addElement(E);
     method public int capacity();
     method @NonNull public Object clone();
-    method public void copyInto(Object[]);
+    method public void copyInto(@NonNull Object[]);
     method public E elementAt(int);
     method @NonNull public java.util.Enumeration<E> elements();
     method public void ensureCapacity(int);
@@ -70791,7 +70801,7 @@
     method public void trimToSize();
     field protected int capacityIncrement;
     field protected int elementCount;
-    field protected Object[] elementData;
+    field @NonNull protected Object[] elementData;
   }
 
   public class WeakHashMap<K, V> extends java.util.AbstractMap<K,V> implements java.util.Map<K,V> {
@@ -71182,7 +71192,7 @@
   public class CopyOnWriteArrayList<E> implements java.lang.Cloneable java.util.List<E> java.util.RandomAccess java.io.Serializable {
     ctor public CopyOnWriteArrayList();
     ctor public CopyOnWriteArrayList(@NonNull java.util.Collection<? extends E>);
-    ctor public CopyOnWriteArrayList(E[]);
+    ctor public CopyOnWriteArrayList(@NonNull E[]);
     method public boolean add(E);
     method public void add(int, E);
     method public boolean addAll(@NonNull java.util.Collection<? extends E>);
@@ -71210,8 +71220,8 @@
     method public E set(int, E);
     method public int size();
     method @NonNull public java.util.List<E> subList(int, int);
-    method public Object[] toArray();
-    method public <T> T[] toArray(T[]);
+    method @NonNull public Object[] toArray();
+    method @NonNull public <T> T[] toArray(@NonNull T[]);
   }
 
   public class CopyOnWriteArraySet<E> extends java.util.AbstractSet<E> implements java.io.Serializable {
@@ -72963,7 +72973,7 @@
     method public void config(@NonNull java.util.function.Supplier<java.lang.String>);
     method public void entering(@Nullable String, @Nullable String);
     method public void entering(@Nullable String, @Nullable String, @Nullable Object);
-    method public void entering(@Nullable String, @Nullable String, Object[]);
+    method public void entering(@Nullable String, @Nullable String, @Nullable Object[]);
     method public void exiting(@Nullable String, @Nullable String);
     method public void exiting(@Nullable String, @Nullable String, @Nullable Object);
     method public void fine(@Nullable String);
@@ -72976,7 +72986,7 @@
     method @NonNull public static java.util.logging.Logger getAnonymousLogger(@Nullable String);
     method @Nullable public java.util.logging.Filter getFilter();
     method @NonNull public static final java.util.logging.Logger getGlobal();
-    method public java.util.logging.Handler[] getHandlers();
+    method @NonNull public java.util.logging.Handler[] getHandlers();
     method @Nullable public java.util.logging.Level getLevel();
     method @NonNull public static java.util.logging.Logger getLogger(@NonNull String);
     method @NonNull public static java.util.logging.Logger getLogger(@NonNull String, @Nullable String);
@@ -72992,7 +73002,7 @@
     method public void log(@NonNull java.util.logging.Level, @Nullable String);
     method public void log(@NonNull java.util.logging.Level, @NonNull java.util.function.Supplier<java.lang.String>);
     method public void log(@NonNull java.util.logging.Level, @Nullable String, @Nullable Object);
-    method public void log(@NonNull java.util.logging.Level, @Nullable String, Object[]);
+    method public void log(@NonNull java.util.logging.Level, @Nullable String, @Nullable Object[]);
     method public void log(@NonNull java.util.logging.Level, @Nullable String, @Nullable Throwable);
     method public void log(@NonNull java.util.logging.Level, @Nullable Throwable, @NonNull java.util.function.Supplier<java.lang.String>);
     method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String);
@@ -73003,8 +73013,8 @@
     method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable Throwable, @NonNull java.util.function.Supplier<java.lang.String>);
     method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String);
     method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, @Nullable Object);
-    method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, Object[]);
-    method public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable java.util.ResourceBundle, @Nullable String, java.lang.Object...);
+    method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, @Nullable Object[]);
+    method public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable java.util.ResourceBundle, @Nullable String, @Nullable java.lang.Object...);
     method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, @Nullable Throwable);
     method public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable java.util.ResourceBundle, @Nullable String, @Nullable Throwable);
     method public void removeHandler(@Nullable java.util.logging.Handler) throws java.lang.SecurityException;
@@ -73266,8 +73276,8 @@
     method public static boolean matches(@NonNull String, @NonNull CharSequence);
     method @NonNull public String pattern();
     method @NonNull public static String quote(@NonNull String);
-    method public String[] split(@NonNull CharSequence, int);
-    method public String[] split(@NonNull CharSequence);
+    method @NonNull public String[] split(@NonNull CharSequence, int);
+    method @NonNull public String[] split(@NonNull CharSequence);
     method @NonNull public java.util.stream.Stream<java.lang.String> splitAsStream(@NonNull CharSequence);
     field public static final int CANON_EQ = 128; // 0x80
     field public static final int CASE_INSENSITIVE = 2; // 0x2
diff --git a/api/system-current.txt b/api/system-current.txt
index e7c7b57..8989344 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -501,6 +501,13 @@
     method public org.json.JSONObject toJson() throws org.json.JSONException;
   }
 
+  public class NotificationManager {
+    method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
+    method @Nullable public android.content.ComponentName getAllowedNotificationAssistantForUser(android.os.UserHandle);
+    method public void setNotificationAssistantAccessGranted(android.content.ComponentName, boolean);
+    method public void setNotificationAssistantAccessGrantedForUser(android.content.ComponentName, android.os.UserHandle, boolean);
+  }
+
   public final class StatsManager {
     method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void addConfig(long, byte[]) throws android.app.StatsManager.StatsUnavailableException;
     method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean addConfiguration(long, byte[]);
@@ -1718,9 +1725,9 @@
   public final class RollbackInfo implements android.os.Parcelable {
     method public int describeContents();
     method public java.util.List<android.content.pm.VersionedPackage> getCausePackages();
+    method public int getCommittedSessionId();
     method public java.util.List<android.content.rollback.PackageRollbackInfo> getPackages();
     method public int getRollbackId();
-    method public int getSessionId();
     method public boolean isStaged();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.rollback.RollbackInfo> CREATOR;
@@ -4095,6 +4102,7 @@
 
   public class CaptivePortal implements android.os.Parcelable {
     ctor public CaptivePortal(android.os.IBinder);
+    method public void logEvent(int, String);
     method public void useNetwork();
     field public static final int APP_RETURN_DISMISSED = 0; // 0x0
     field public static final int APP_RETURN_UNWANTED = 1; // 0x1
@@ -9404,17 +9412,6 @@
     method public void setContentCaptureFeatureEnabled(boolean);
   }
 
-  public final class UserDataRemovalRequest implements android.os.Parcelable {
-    method @NonNull public String getPackageName();
-    method @NonNull public java.util.List<android.view.contentcapture.UserDataRemovalRequest.UriRequest> getUriRequests();
-    method public boolean isForEverything();
-  }
-
-  public final class UserDataRemovalRequest.UriRequest {
-    method @NonNull public android.net.Uri getUri();
-    method @NonNull public boolean isRecursive();
-  }
-
   public final class ViewNode extends android.app.assist.AssistStructure.ViewNode {
     method @Nullable public android.view.autofill.AutofillId getParentAutofillId();
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 4fc1757..91d0019 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -804,6 +804,7 @@
 
   public class CaptivePortal implements android.os.Parcelable {
     ctor public CaptivePortal(android.os.IBinder);
+    method public void logEvent(int, String);
     method public void useNetwork();
     field public static final int APP_RETURN_DISMISSED = 0; // 0x0
     field public static final int APP_RETURN_UNWANTED = 1; // 0x1
@@ -2386,6 +2387,10 @@
     method public boolean isSystemGroup();
   }
 
+  public abstract class LayoutInflater {
+    method public void setPrecompiledLayoutsEnabledForTesting(boolean);
+  }
+
   public final class MotionEvent extends android.view.InputEvent implements android.os.Parcelable {
     method public void setActionButton(int);
     method public void setButtonState(int);
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
index 4e4b8f3..f37d2be 100644
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
+++ b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
@@ -55,6 +55,10 @@
         Status status = statsCompanionServiceCopy->pullData(mTagId, &returned_value);
         if (!status.isOk()) {
             ALOGW("StatsCompanionServicePuller::pull failed for %d", mTagId);
+            StatsdStats::getInstance().noteStatsCompanionPullFailed(mTagId);
+            if (status.exceptionCode() == Status::Exception::EX_TRANSACTION_FAILED) {
+                StatsdStats::getInstance().noteStatsCompanionPullBinderTransactionFailed(mTagId);
+            }
             return false;
         }
         data->clear();
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index ba7bcc4..a6ba2ca 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -231,6 +231,9 @@
     if (kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end()) {
         bool ret = kAllPullAtomInfo.find(tagId)->second.puller->Pull(data);
         VLOG("pulled %d items", (int)data->size());
+        if (!ret) {
+            StatsdStats::getInstance().notePullFailed(tagId);
+        }
         return ret;
     } else {
         VLOG("Unknown tagId %d", tagId);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index f4d0144..37ccad5 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -403,6 +403,60 @@
     mSystemServerRestartSec.push_back(timeSec);
 }
 
+void StatsdStats::notePullFailed(int atomId) {
+    lock_guard<std::mutex> lock(mLock);
+    mPulledAtomStats[atomId].pullFailed++;
+}
+
+void StatsdStats::noteStatsCompanionPullFailed(int atomId) {
+    lock_guard<std::mutex> lock(mLock);
+    mPulledAtomStats[atomId].statsCompanionPullFailed++;
+}
+
+void StatsdStats::noteStatsCompanionPullBinderTransactionFailed(int atomId) {
+    lock_guard<std::mutex> lock(mLock);
+    mPulledAtomStats[atomId].statsCompanionPullBinderTransactionFailed++;
+}
+
+void StatsdStats::noteEmptyData(int atomId) {
+    lock_guard<std::mutex> lock(mLock);
+    mPulledAtomStats[atomId].emptyData++;
+}
+
+void StatsdStats::noteHardDimensionLimitReached(int metricId) {
+    lock_guard<std::mutex> lock(mLock);
+    getAtomMetricStats(metricId).hardDimensionLimitReached++;
+}
+
+void StatsdStats::noteLateLogEventSkipped(int metricId) {
+    lock_guard<std::mutex> lock(mLock);
+    getAtomMetricStats(metricId).lateLogEventSkipped++;
+}
+
+void StatsdStats::noteSkippedForwardBuckets(int metricId) {
+    lock_guard<std::mutex> lock(mLock);
+    getAtomMetricStats(metricId).skippedForwardBuckets++;
+}
+
+void StatsdStats::noteBadValueType(int metricId) {
+    lock_guard<std::mutex> lock(mLock);
+    getAtomMetricStats(metricId).badValueType++;
+}
+
+void StatsdStats::noteConditionChangeInNextBucket(int metricId) {
+    lock_guard<std::mutex> lock(mLock);
+    getAtomMetricStats(metricId).conditionChangeInNextBucket++;
+}
+
+StatsdStats::AtomMetricStats& StatsdStats::getAtomMetricStats(int metricId) {
+    auto atomMetricStatsIter = mAtomMetricStats.find(metricId);
+    if (atomMetricStatsIter != mAtomMetricStats.end()) {
+        return atomMetricStatsIter->second;
+    }
+    auto emplaceResult = mAtomMetricStats.emplace(metricId, AtomMetricStats());
+    return emplaceResult.first->second;
+}
+
 void StatsdStats::reset() {
     lock_guard<std::mutex> lock(mLock);
     resetInternalLocked();
@@ -442,6 +496,7 @@
         pullStats.second.pullTimeout = 0;
         pullStats.second.pullExceedMaxDelay = 0;
     }
+    mAtomMetricStats.clear();
 }
 
 string buildTimeString(int64_t timeSec) {
@@ -713,6 +768,10 @@
         android::os::statsd::writePullerStatsToStream(pair, &proto);
     }
 
+    for (const auto& pair : mAtomMetricStats) {
+        android::os::statsd::writeAtomMetricStatsToStream(pair, &proto);
+    }
+
     if (mAnomalyAlarmRegisteredStats > 0) {
         uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ANOMALY_ALARM_STATS);
         proto.write(FIELD_TYPE_INT32 | FIELD_ID_ANOMALY_ALARMS_REGISTERED,
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index dc647f8..01e9ca1 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -318,6 +318,53 @@
     void noteLogLost(int32_t wallClockTimeSec, int32_t count, int lastError);
 
     /**
+     * Records that the pull of an atom has failed
+     */
+    void notePullFailed(int atomId);
+
+    /**
+     * Records that the pull of StatsCompanionService atom has failed
+     */
+    void noteStatsCompanionPullFailed(int atomId);
+
+    /**
+     * Records that the pull of a StatsCompanionService atom has failed due to a failed binder
+     * transaction. This can happen when StatsCompanionService returns too
+     * much data (the max Binder parcel size is 1MB)
+     */
+    void noteStatsCompanionPullBinderTransactionFailed(int atomId);
+
+    /**
+     * A pull with no data occurred
+     */
+    void noteEmptyData(int atomId);
+
+    /**
+     * Hard limit was reached in the cardinality of an atom
+     */
+    void noteHardDimensionLimitReached(int atomId);
+
+    /**
+     * A log event was too late, arrived in the wrong bucket and was skipped
+     */
+    void noteLateLogEventSkipped(int atomId);
+
+    /**
+     * Buckets were skipped as time elapsed without any data for them
+     */
+    void noteSkippedForwardBuckets(int atomId);
+
+    /**
+     * An unsupported value type was received
+     */
+    void noteBadValueType(int atomId);
+
+    /**
+     * A condition change was too late, arrived in the wrong bucket and was skipped
+     */
+    void noteConditionChangeInNextBucket(int atomId);
+
+    /**
      * Reset the historical stats. Including all stats in icebox, and the tracked stats about
      * metrics, matchers, and atoms. The active configs will be kept and StatsdStats will continue
      * to collect stats after reset() has been called.
@@ -349,8 +396,20 @@
         long dataError = 0;
         long pullTimeout = 0;
         long pullExceedMaxDelay = 0;
+        long pullFailed = 0;
+        long statsCompanionPullFailed = 0;
+        long statsCompanionPullBinderTransactionFailed = 0;
+        long emptyData = 0;
     } PulledAtomStats;
 
+    typedef struct {
+        long hardDimensionLimitReached = 0;
+        long lateLogEventSkipped = 0;
+        long skippedForwardBuckets = 0;
+        long badValueType = 0;
+        long conditionChangeInNextBucket = 0;
+    } AtomMetricStats;
+
 private:
     StatsdStats();
 
@@ -378,6 +437,9 @@
     // Maps PullAtomId to its stats. The size is capped by the puller atom counts.
     std::map<int, PulledAtomStats> mPulledAtomStats;
 
+    // Maps metric ID to its stats. The size is capped by the number of metrics.
+    std::map<int, AtomMetricStats> mAtomMetricStats;
+
     struct LogLossStats {
         LogLossStats(int32_t sec, int32_t count, int32_t error)
             : mWallClockSec(sec), mCount(count), mLastError(error) {
@@ -414,6 +476,12 @@
 
     void addToIceBoxLocked(std::shared_ptr<ConfigStats>& stats);
 
+    /**
+     * Get a reference to AtomMetricStats for a metric. If none exists, create it. The reference
+     * will live as long as `this`.
+     */
+    StatsdStats::AtomMetricStats& getAtomMetricStats(int metricId);
+
     FRIEND_TEST(StatsdStatsTest, TestValidConfigAdd);
     FRIEND_TEST(StatsdStatsTest, TestInvalidConfigAdd);
     FRIEND_TEST(StatsdStatsTest, TestConfigRemove);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 5645461..6aa8e84 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -322,6 +322,7 @@
     if (eventTimeNs < mCurrentBucketStartTimeNs) {
         VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
              (long long)mCurrentBucketStartTimeNs);
+        StatsdStats::getInstance().noteConditionChangeInNextBucket(mMetricId);
         return;
     }
 
@@ -359,6 +360,12 @@
     }
     StatsdStats::getInstance().notePullDelay(mPullTagId, pullDelayNs);
 
+    if (timestampNs < mCurrentBucketStartTimeNs) {
+        // The data will be skipped in onMatchedLogEventInternalLocked, but we don't want to report
+        // for every event, just the pull
+        StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
+    }
+
     for (const auto& data : allData) {
         // make a copy before doing and changes
         LogEvent localCopy = data->makeCopy();
@@ -380,6 +387,7 @@
     if (mCondition) {
         if (allData.size() == 0) {
             VLOG("Data pulled is empty");
+            StatsdStats::getInstance().noteEmptyData(mPullTagId);
             return;
         }
         // For scheduled pulled data, the effective event time is snap to the nearest
@@ -394,6 +402,7 @@
         if (bucketEndTime < mCurrentBucketStartTimeNs) {
             VLOG("Skip bucket end pull due to late arrival: %lld vs %lld", (long long)bucketEndTime,
                  (long long)mCurrentBucketStartTimeNs);
+            StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
             return;
         }
         for (const auto& data : allData) {
@@ -442,6 +451,7 @@
         if (newTupleCount > mDimensionHardLimit) {
             ALOGE("ValueMetric %lld dropping data for dimension key %s", (long long)mMetricId,
                   newKey.toString().c_str());
+            StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
             return true;
         }
     }
@@ -539,6 +549,7 @@
         Value value;
         if (!getDoubleOrLong(event, matcher, value)) {
             VLOG("Failed to get value %d from event %s", i, event.ToString().c_str());
+            StatsdStats::getInstance().noteBadValueType(mMetricId);
             return;
         }
         interval.seenNewData = true;
@@ -656,6 +667,7 @@
 
     if (numBucketsForward > 1) {
         VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
+        StatsdStats::getInstance().noteSkippedForwardBuckets(mMetricId);
         // take base again in future good bucket.
         resetBase();
     }
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index e8de875..cca09ac 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -403,9 +403,23 @@
         optional int64 data_error = 9;
         optional int64 pull_timeout = 10;
         optional int64 pull_exceed_max_delay = 11;
+        optional int64 pull_failed = 12;
+        optional int64 stats_companion_pull_failed = 13;
+        optional int64 stats_companion_pull_binder_transaction_failed = 14;
+        optional int64 empty_data = 15;
     }
     repeated PulledAtomStats pulled_atom_stats = 10;
 
+    message AtomMetricStats {
+      optional int64 metric_id = 1;
+      optional int64 hard_dimension_limit_reached = 2;
+      optional int64 late_log_event_skipped = 3;
+      optional int64 skipped_forward_buckets = 4;
+      optional int64 bad_value_type = 5;
+      optional int64 condition_change_in_next_bucket = 6;
+    }
+    repeated AtomMetricStats atom_metric_stats = 17;
+
     message LoggerErrorStats {
         optional int32 logger_disconnection_sec = 1;
         optional int32 error_code = 2;
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 7de0bb3..9c9985e 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -66,6 +66,18 @@
 const int FIELD_ID_DATA_ERROR = 9;
 const int FIELD_ID_PULL_TIMEOUT = 10;
 const int FIELD_ID_PULL_EXCEED_MAX_DELAY = 11;
+const int FIELD_ID_PULL_FAILED = 12;
+const int FIELD_ID_STATS_COMPANION_FAILED = 13;
+const int FIELD_ID_STATS_COMPANION_BINDER_TRANSACTION_FAILED = 14;
+const int FIELD_ID_EMPTY_DATA = 15;
+// for AtomMetricStats proto
+const int FIELD_ID_ATOM_METRIC_STATS = 17;
+const int FIELD_ID_METRIC_ID = 1;
+const int FIELD_ID_HARD_DIMENSION_LIMIT_REACHED = 2;
+const int FIELD_ID_LATE_LOG_EVENT_SKIPPED = 3;
+const int FIELD_ID_SKIPPED_FORWARD_BUCKETS = 4;
+const int FIELD_ID_BAD_VALUE_TYPE = 5;
+const int FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET = 6;
 
 namespace {
 
@@ -456,6 +468,32 @@
                        (long long)pair.second.pullTimeout);
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_EXCEED_MAX_DELAY,
                        (long long)pair.second.pullExceedMaxDelay);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_FAILED,
+                       (long long)pair.second.pullFailed);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_STATS_COMPANION_FAILED,
+                       (long long)pair.second.statsCompanionPullFailed);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_STATS_COMPANION_BINDER_TRANSACTION_FAILED,
+                       (long long)pair.second.statsCompanionPullBinderTransactionFailed);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_EMPTY_DATA,
+                       (long long)pair.second.emptyData);
+    protoOutput->end(token);
+}
+
+void writeAtomMetricStatsToStream(const std::pair<int, StatsdStats::AtomMetricStats> &pair,
+                                  util::ProtoOutputStream *protoOutput) {
+    uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM_METRIC_STATS |
+                                        FIELD_COUNT_REPEATED);
+    protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_METRIC_ID, (int32_t)pair.first);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_HARD_DIMENSION_LIMIT_REACHED,
+                       (long long)pair.second.hardDimensionLimitReached);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_LATE_LOG_EVENT_SKIPPED,
+                       (long long)pair.second.lateLogEventSkipped);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_SKIPPED_FORWARD_BUCKETS,
+                       (long long)pair.second.skippedForwardBuckets);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BAD_VALUE_TYPE,
+                       (long long)pair.second.badValueType);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET,
+                       (long long)pair.second.conditionChangeInNextBucket);
     protoOutput->end(token);
 }
 
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index 61f31eb..dcea0e6 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -73,6 +73,10 @@
 void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair,
                               util::ProtoOutputStream* protoOutput);
 
+// Helper function to write AtomMetricStats to ProtoOutputStream
+void writeAtomMetricStatsToStream(const std::pair<int, StatsdStats::AtomMetricStats> &pair,
+                                  util::ProtoOutputStream *protoOutput);
+
 template<class T>
 bool parseProtoOutputStream(util::ProtoOutputStream& protoOutput, T* message) {
     std::string pbBytes;
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 8e7a58b..a748959 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1942,7 +1942,6 @@
 Lcom/android/internal/R$id;->titleDivider:I
 Lcom/android/internal/R$id;->titleDividerTop:I
 Lcom/android/internal/R$id;->title_container:I
-Lcom/android/internal/R$id;->title_icon:I
 Lcom/android/internal/R$id;->title_template:I
 Lcom/android/internal/R$id;->topPanel:I
 Lcom/android/internal/R$id;->up:I
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index ce5d8a5..eae7d6b 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -28,15 +28,12 @@
 import android.content.Intent;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
-import android.hardware.input.InputManager;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.IWindowManager;
-import android.view.InputDevice;
-import android.view.MotionEvent;
 import android.view.SurfaceControl;
 import android.view.SurfaceHolder;
 import android.view.SurfaceSession;
@@ -51,9 +48,7 @@
 import java.util.List;
 
 /**
- * Activity container that allows launching activities into itself and does input forwarding.
- * <p>Creation of this view is only allowed to callers who have
- * {@link android.Manifest.permission#INJECT_EVENTS} permission.
+ * Activity container that allows launching activities into itself.
  * <p>Activity launching into this container is restricted by the same rules that apply to launching
  * on VirtualDisplays.
  * @hide
@@ -76,9 +71,8 @@
     private StateCallback mActivityViewCallback;
 
     private IActivityTaskManager mActivityTaskManager;
-    private IInputForwarder mInputForwarder;
-    // Temp container to store view coordinates on screen.
-    private final int[] mLocationOnScreen = new int[2];
+    // Temp container to store view coordinates in window.
+    private final int[] mLocationInWindow = new int[2];
 
     private TaskStackListener mTaskStackListener;
 
@@ -280,7 +274,7 @@
     }
 
     /**
-     * Triggers an update of {@link ActivityView}'s location on screen to properly set touch exclude
+     * Triggers an update of {@link ActivityView}'s location in window to properly set touch exclude
      * regions and avoid focus switches by touches on this view.
      */
     public void onLocationChanged() {
@@ -295,45 +289,14 @@
     /** Send current location and size to the WM to set tap exclude region for this view. */
     private void updateLocation() {
         try {
-            getLocationOnScreen(mLocationOnScreen);
+            getLocationInWindow(mLocationInWindow);
             WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
-                    mLocationOnScreen[0], mLocationOnScreen[1], getWidth(), getHeight());
+                    mLocationInWindow[0], mLocationInWindow[1], getWidth(), getHeight());
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
         }
     }
 
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        return injectInputEvent(event) || super.onTouchEvent(event);
-    }
-
-    @Override
-    public boolean onGenericMotionEvent(MotionEvent event) {
-        if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
-            if (injectInputEvent(event)) {
-                return true;
-            }
-        }
-        return super.onGenericMotionEvent(event);
-    }
-
-    private boolean injectInputEvent(MotionEvent event) {
-        if (mInputForwarder != null) {
-            try {
-                // The touch event that the ActivityView gets is in View space, but the event needs
-                // to get forwarded in screen space. This offsets the touch event by the location
-                // the ActivityView is on screen and sends it to the input forwarder.
-                getLocationOnScreen(mLocationOnScreen);
-                event.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
-                return mInputForwarder.forwardEvent(event);
-            } catch (RemoteException e) {
-                e.rethrowAsRuntimeException();
-            }
-        }
-        return false;
-    }
-
     private class SurfaceCallback implements SurfaceHolder.Callback {
         @Override
         public void surfaceCreated(SurfaceHolder surfaceHolder) {
@@ -416,7 +379,6 @@
         }
 
         mTmpTransaction.show(mRootSurfaceControl).apply();
-        mInputForwarder = InputManager.getInstance().createInputForwarder(displayId);
         mTaskStackListener = new TaskStackListenerImpl();
         try {
             mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
@@ -432,9 +394,6 @@
 
         mSurfaceView.getHolder().removeCallback(mSurfaceCallback);
 
-        if (mInputForwarder != null) {
-            mInputForwarder = null;
-        }
         cleanTapExcludeRegion();
 
         if (mTaskStackListener != null) {
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 8953940..df04a6b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -65,6 +65,9 @@
     boolean areNotificationsEnabled(String pkg);
     int getPackageImportance(String pkg);
 
+    boolean shouldHideSilentStatusIcons(String callingPkg);
+    void setHideSilentStatusIcons(boolean hide);
+
     void setBubblesAllowed(String pkg, int uid, boolean allowed);
     boolean areBubblesAllowed(String pkg);
     boolean areBubblesAllowedForPackage(String pkg, int uid);
@@ -151,6 +154,8 @@
     void setNotificationAssistantAccessGrantedForUser(in ComponentName assistant, int userId, boolean enabled);
     List<String> getEnabledNotificationListenerPackages();
     List<ComponentName> getEnabledNotificationListeners(int userId);
+    ComponentName getAllowedNotificationAssistantForUser(int userId);
+    ComponentName getAllowedNotificationAssistant();
 
     int getZenMode();
     ZenModeConfig getZenModeConfig();
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 621f134..6a1ff29 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -353,7 +354,8 @@
     public static final int IMPORTANCE_MIN = 1;
 
     /**
-     * Low notification importance: shows everywhere, but is not intrusive.
+     * Low notification importance: Shows in the shade, and potentially in the status bar
+     * (see {@link #shouldHideSilentStatusBarIcons()}), but is not audibly intrusive.
      */
     public static final int IMPORTANCE_LOW = 2;
 
@@ -1153,6 +1155,19 @@
         }
     }
 
+    /**
+     * Checks whether the user has approved a given
+     * {@link android.service.notification.NotificationAssistantService}.
+     *
+     * <p>
+     * The assistant service must belong to the calling app.
+     *
+     * <p>
+     * Apps can request notification assistant access by sending the user to the activity that
+     * matches the system intent action
+     * TODO: STOPSHIP: Add correct intent
+     * {@link android.provider.Settings#ACTION_MANAGE_DEFAULT_APPS_SETTINGS}.
+     */
     public boolean isNotificationAssistantAccessGranted(ComponentName assistant) {
         INotificationManager service = getService();
         try {
@@ -1162,6 +1177,22 @@
         }
     }
 
+    /**
+     * Returns whether the user wants silent notifications (see {@link #IMPORTANCE_LOW} to appear
+     * in the status bar.
+     *
+     * <p>Only available for {@link #isNotificationListenerAccessGranted(ComponentName) notification
+     * listeners}.
+     */
+    public boolean shouldHideSilentStatusBarIcons() {
+        INotificationManager service = getService();
+        try {
+            return service.shouldHideSilentStatusIcons(mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** @hide */
     public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
         INotificationManager service = getService();
@@ -1248,6 +1279,45 @@
         }
     }
 
+    /**
+     * Grants/revokes Notification Assistant access to {@code assistant} for current user.
+     *
+     * @param assistant Name of component to grant/revoke access or {@code null} to revoke access to
+     *                  current assistant
+     * @param granted Grant/revoke access
+     * @hide
+     */
+    @SystemApi
+    public void setNotificationAssistantAccessGranted(ComponentName assistant, boolean granted) {
+        INotificationManager service = getService();
+        try {
+            service.setNotificationAssistantAccessGranted(assistant, granted);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Grants/revokes Notification Assistant access to {@code assistant} for given user.
+     *
+     * @param assistant Name of component to grant/revoke access or {@code null} to revoke access to
+     *                  current assistant
+     * @param user handle to associate assistant with
+     * @param granted Grant/revoke access
+     * @hide
+     */
+    @SystemApi
+    public void setNotificationAssistantAccessGrantedForUser(ComponentName assistant,
+            UserHandle user, boolean granted) {
+        INotificationManager service = getService();
+        try {
+            service.setNotificationAssistantAccessGrantedForUser(assistant, user.getIdentifier(),
+                    granted);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** @hide */
     public List<ComponentName> getEnabledNotificationListeners(int userId) {
         INotificationManager service = getService();
@@ -1258,6 +1328,29 @@
         }
     }
 
+    /** @hide */
+    @SystemApi
+    public @Nullable ComponentName getAllowedNotificationAssistantForUser(UserHandle user) {
+        INotificationManager service = getService();
+        try {
+            return service.getAllowedNotificationAssistantForUser(user.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** @hide */
+    @SystemApi
+    public @Nullable ComponentName getAllowedNotificationAssistant() {
+        INotificationManager service = getService();
+        try {
+            return service.getAllowedNotificationAssistant();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+
     private Context mContext;
 
     private static void checkRequired(String name, Object value) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 65ea635..a3021f3 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -971,7 +971,8 @@
      *
      * @param target The Intent that the user will be selecting an activity
      * to perform.
-     * @param title Optional title that will be displayed in the chooser.
+     * @param title Optional title that will be displayed in the chooser,
+     * only when the target action is not ACTION_SEND or ACTION_SEND_MULTIPLE.
      * @return Return a new Intent object that you can hand to
      * {@link Context#startActivity(Intent) Context.startActivity()} and
      * related methods.
@@ -998,7 +999,8 @@
      *
      * @param target The Intent that the user will be selecting an activity
      * to perform.
-     * @param title Optional title that will be displayed in the chooser.
+     * @param title Optional title that will be displayed in the chooser,
+     * only when the target action is not ACTION_SEND or ACTION_SEND_MULTIPLE.
      * @param sender Optional IntentSender to be called when a choice is made.
      * @return Return a new Intent object that you can hand to
      * {@link Context#startActivity(Intent) Context.startActivity()} and
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index 4644a83..d4ed35a 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -16,10 +16,14 @@
 
 package android.content.rollback;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.content.pm.VersionedPackage;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.IntArray;
+
+import java.util.ArrayList;
 
 /**
  * Information about a rollback available for a particular package.
@@ -33,6 +37,38 @@
     private final VersionedPackage mVersionRolledBackTo;
 
     /**
+     * Encapsulates information required to restore a snapshot of an app's userdata.
+     *
+     * @hide
+     */
+    public static class RestoreInfo {
+        public final int userId;
+        public final int appId;
+        public final String seInfo;
+
+        public RestoreInfo(int userId, int appId, String seInfo) {
+            this.userId = userId;
+            this.appId = appId;
+            this.seInfo = seInfo;
+        }
+    }
+
+    /*
+     * The list of users for which we need to backup userdata for this package. Backups of
+     * credential encrypted data are listed as pending if the user hasn't unlocked their device
+     * with credentials yet.
+     */
+    // NOTE: Not a part of the Parcelable representation of this object.
+    private final IntArray mPendingBackups;
+
+    /**
+     * The list of users for which we need to restore userdata for this package. This field is
+     * non-null only after a rollback for this package has been committed.
+     */
+    // NOTE: Not a part of the Parcelable representation of this object.
+    private final ArrayList<RestoreInfo> mPendingRestores;
+
+    /**
      * Returns the name of the package to roll back from.
      */
     public String getPackageName() {
@@ -54,15 +90,46 @@
     }
 
     /** @hide */
+    public IntArray getPendingBackups() {
+        return mPendingBackups;
+    }
+
+    /** @hide */
+    public ArrayList<RestoreInfo> getPendingRestores() {
+        return mPendingRestores;
+    }
+
+    /** @hide */
+    public RestoreInfo getRestoreInfo(int userId) {
+        for (RestoreInfo ri : mPendingRestores) {
+            if (ri.userId == userId) {
+                return ri;
+            }
+        }
+
+        return null;
+    }
+
+    /** @hide */
+    public void removeRestoreInfo(RestoreInfo ri) {
+        mPendingRestores.remove(ri);
+    }
+
+    /** @hide */
     public PackageRollbackInfo(VersionedPackage packageRolledBackFrom,
-            VersionedPackage packageRolledBackTo) {
+            VersionedPackage packageRolledBackTo,
+            @NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores) {
         this.mVersionRolledBackFrom = packageRolledBackFrom;
         this.mVersionRolledBackTo = packageRolledBackTo;
+        this.mPendingBackups = pendingBackups;
+        this.mPendingRestores = pendingRestores;
     }
 
     private PackageRollbackInfo(Parcel in) {
         this.mVersionRolledBackFrom = VersionedPackage.CREATOR.createFromParcel(in);
         this.mVersionRolledBackTo = VersionedPackage.CREATOR.createFromParcel(in);
+        this.mPendingRestores = null;
+        this.mPendingBackups = null;
     }
 
     @Override
diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java
index 1111b43..3fd2476 100644
--- a/core/java/android/content/rollback/RollbackInfo.java
+++ b/core/java/android/content/rollback/RollbackInfo.java
@@ -83,7 +83,7 @@
      * Returns the session ID for the committed rollback for staged rollbacks.
      * Only applicable for rollbacks that have been committed.
      */
-    public int getSessionId() {
+    public int getCommittedSessionId() {
         // TODO: Support rollback of staged installs.
         return PackageInstaller.SessionInfo.INVALID_ID;
     }
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index f9c2c3e..a1b0803 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -2644,10 +2644,29 @@
              * Sets the maximum number of milliseconds that SQLite connection is allowed to be idle
              * before it is closed and removed from the pool.
              *
+             * <p>DO NOT USE this method unless you fully understand the implication
+             * of what it does.
+             * A connection timeout allows the system to internally close a connection to a SQLite
+             * database after a given timeout.
+             * This is good for reducing app's memory consumption, but it has
+             * side effects that are hard to predict. For example, SQLite internally maintains
+             * a lot of "per-connection" states that apps can typically modify with a {@code PRAGMA}
+             * statement, and such states will be reset once the connection is closed.
+             * The system does not provide a callback that would allow apps to
+             * reconfigure a newly created connection and thus there's no way to re-configure
+             * connections when they're re-made internally. Do not use it unless you're sure
+             * your app uses no per-connection states.
+             *
              * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE}
              * to allow unlimited idle connections.
+             *
+             * @see SQLiteOpenHelper#setIdleConnectionTimeout(long)
+             *
+             * @deprecated DO NOT USE this method unless you fully understand the implication
+             * of what it does.
              */
             @NonNull
+            @Deprecated
             public Builder setIdleConnectionTimeout(
                     @IntRange(from = 0) long idleConnectionTimeoutMs) {
                 Preconditions.checkArgument(idleConnectionTimeoutMs >= 0,
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 19c6745..ceeecbc 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -263,9 +263,21 @@
      * <p>This method should be called from the constructor of the subclass,
      * before opening the database
      *
+     * <p>DO NOT USE this method unless you fully understand the implication
+     * of what it does.
+     * See the javadoc of
+     * {@link SQLiteDatabase.OpenParams.Builder#setIdleConnectionTimeout(long)}
+     * for the details.
+     *
      * @param idleConnectionTimeoutMs timeout in milliseconds. Use {@link Long#MAX_VALUE} value
      * to allow unlimited idle connections.
+     *
+     * @see SQLiteDatabase.OpenParams.Builder#setIdleConnectionTimeout(long)
+     *
+     * @deprecated DO NOT USE this method unless you fully understand the implication
+     * of what it does.
      */
+    @Deprecated
     public void setIdleConnectionTimeout(@IntRange(from = 0) final long idleConnectionTimeoutMs) {
         synchronized (this) {
             if (mDatabase != null && mDatabase.isOpen()) {
diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java
index 3b01266..3ab35e1 100644
--- a/core/java/android/net/CaptivePortal.java
+++ b/core/java/android/net/CaptivePortal.java
@@ -117,4 +117,17 @@
         } catch (RemoteException e) {
         }
     }
+
+    /**
+     * Log a captive portal login event.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public void logEvent(int eventId, String packageName) {
+        try {
+            ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName);
+        } catch (RemoteException e) {
+        }
+    }
 }
diff --git a/core/java/android/net/ICaptivePortal.aidl b/core/java/android/net/ICaptivePortal.aidl
index 56ae57d..707b4f6 100644
--- a/core/java/android/net/ICaptivePortal.aidl
+++ b/core/java/android/net/ICaptivePortal.aidl
@@ -22,4 +22,5 @@
  */
 oneway interface ICaptivePortal {
     void appResponse(int response);
+    void logEvent(int eventId, String packageName);
 }
diff --git a/core/java/android/net/INetworkMonitorCallbacks.aidl b/core/java/android/net/INetworkMonitorCallbacks.aidl
index 0bc2575..a8682f9 100644
--- a/core/java/android/net/INetworkMonitorCallbacks.aidl
+++ b/core/java/android/net/INetworkMonitorCallbacks.aidl
@@ -26,4 +26,5 @@
     void notifyPrivateDnsConfigResolved(in PrivateDnsConfigParcel config);
     void showProvisioningNotification(String action);
     void hideProvisioningNotification();
+    void logCaptivePortalLoginEvent(int eventId, String packageName);
 }
\ No newline at end of file
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 8a52f1f..3e5bd4b 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -138,8 +138,8 @@
      * Action used to help apps show calendar events in the managed profile.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_VIEW_WORK_CALENDAR_EVENT =
-            "android.provider.calendar.action.VIEW_WORK_CALENDAR_EVENT";
+    public static final String ACTION_VIEW_MANAGED_PROFILE_CALENDAR_EVENT =
+            "android.provider.calendar.action.VIEW_MANAGED_PROFILE_CALENDAR_EVENT";
 
     /**
      * Intent Extras key: {@link EventsColumns#CUSTOM_APP_URI} for the event in
@@ -166,7 +166,7 @@
     public static final String EXTRA_EVENT_ALL_DAY = "allDay";
 
     /**
-     * Intent Extras key: The id of an event.
+     * Intent Extras key: An extra of type {@code long} holding the id of an event.
      */
     public static final String EXTRA_EVENT_ID = "id";
 
@@ -218,7 +218,7 @@
      * When this API is called, the system will attempt to start an activity
      * in the managed profile with an intent targeting the same caller package.
      * The intent will have its action set to
-     * {@link CalendarContract#ACTION_VIEW_WORK_CALENDAR_EVENT} and contain extras
+     * {@link CalendarContract#ACTION_VIEW_MANAGED_PROFILE_CALENDAR_EVENT} and contain extras
      * corresponding to the API's arguments. A calendar app intending to support
      * cross-profile events viewing should handle this intent, parse the arguments
      * and show the appropriate UI.
@@ -226,10 +226,10 @@
      * @param context the context.
      * @param eventId the id of the event to be viewed. Will be put into {@link #EXTRA_EVENT_ID}
      *                field of the intent.
-     * @param start the start time of the event. Will be put into {@link #EXTRA_EVENT_BEGIN_TIME}
-     *              field of the intent.
-     * @param end the end time of the event. Will be put into {@link #EXTRA_EVENT_END_TIME} field
-     *            of the intent.
+     * @param startMs the start time of the event in milliseconds since epoch.
+     *                Will be put into {@link #EXTRA_EVENT_BEGIN_TIME} field of the intent.
+     * @param endMs the end time of the event in milliseconds since epoch.
+     *              Will be put into {@link #EXTRA_EVENT_END_TIME} field of the intent.
      * @param allDay if the event is an all-day event. Will be put into
      *               {@link #EXTRA_EVENT_ALL_DAY} field of the intent.
      * @param flags flags to be set on the intent via {@link Intent#setFlags}
@@ -241,12 +241,12 @@
      * @see #EXTRA_EVENT_ALL_DAY
      */
     public static boolean startViewCalendarEventInManagedProfile(@NonNull Context context,
-            long eventId, long start, long end, boolean allDay, int flags) {
+            long eventId, long startMs, long endMs, boolean allDay, int flags) {
         Preconditions.checkNotNull(context, "Context is null");
         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
-        return dpm.startViewCalendarEventInManagedProfile(eventId, start,
-                end, allDay, flags);
+        return dpm.startViewCalendarEventInManagedProfile(eventId, startMs,
+                endMs, allDay, flags);
     }
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 794c2f1..5151e29 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10521,8 +10521,10 @@
         /**
          * Setting to enable connected MAC randomization in Wi-Fi; disabled by default, and
          * setting to 1 will enable it. In the future, additional values may be supported.
+         * @deprecated MAC randomization is now a per-network setting
          * @hide
          */
+        @Deprecated
         public static final String WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED =
                 "wifi_connected_mac_randomization_enabled";
 
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 1ddc099e..22104b5 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -33,6 +33,7 @@
     void onListenerConnected(in NotificationRankingUpdate update);
     void onNotificationPosted(in IStatusBarNotificationHolder notificationHolder,
             in NotificationRankingUpdate update);
+    void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons);
     // stats only for assistant
     void onNotificationRemoved(in IStatusBarNotificationHolder notificationHolder,
             in NotificationRankingUpdate update, in NotificationStats stats, int reason);
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index c734b63..d4e8879 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -469,6 +469,17 @@
     }
 
     /**
+     * Implement this method to be notified when the behavior of silent notifications in the status
+     * bar changes. See {@link NotificationManager#shouldHideSilentStatusBarIcons()}.
+     *
+     * @param hideSilentStatusIcons whether or not status bar icons should be hidden for silent
+     *                              notifications
+     */
+    public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+        // optional
+    }
+
+    /**
      * Implement this method to learn about notification channel modifications.
      *
      * <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
@@ -1411,6 +1422,12 @@
             mHandler.obtainMessage(
                     MyHandler.MSG_ON_NOTIFICATION_CHANNEL_GROUP_MODIFIED, args).sendToTarget();
         }
+
+        @Override
+        public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+            mHandler.obtainMessage(MyHandler.MSG_ON_STATUS_BAR_ICON_BEHAVIOR_CHANGED,
+                    hideSilentStatusIcons).sendToTarget();
+        }
     }
 
     /**
@@ -2142,6 +2159,7 @@
         public static final int MSG_ON_INTERRUPTION_FILTER_CHANGED = 6;
         public static final int MSG_ON_NOTIFICATION_CHANNEL_MODIFIED = 7;
         public static final int MSG_ON_NOTIFICATION_CHANNEL_GROUP_MODIFIED = 8;
+        public static final int MSG_ON_STATUS_BAR_ICON_BEHAVIOR_CHANGED = 9;
 
         public MyHandler(Looper looper) {
             super(looper, null, false);
@@ -2207,6 +2225,10 @@
                     int modificationType = (int) args.arg4;
                     onNotificationChannelGroupModified(pkgName, user, group, modificationType);
                 } break;
+
+                case MSG_ON_STATUS_BAR_ICON_BEHAVIOR_CHANGED: {
+                    onStatusBarIconsBehaviorChanged((Boolean) msg.obj);
+                } break;
             }
         }
     }
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index eb41e07..59e562f 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -41,12 +41,14 @@
 import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.accessibility.AccessibilityRequestPreparer;
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
 
 import java.util.ArrayList;
@@ -64,8 +66,11 @@
  * called from the interaction connection ViewAncestor gives the system to
  * talk to it and a corresponding *UiThread method that is executed on the
  * UI thread.
+ *
+ * @hide
  */
-final class AccessibilityInteractionController {
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public final class AccessibilityInteractionController {
 
     private static final String LOG_TAG = "AccessibilityInteractionController";
 
@@ -85,7 +90,7 @@
 
     private final Object mLock = new Object();
 
-    private final Handler mHandler;
+    private final PrivateHandler mHandler;
 
     private final ViewRootImpl mViewRootImpl;
 
@@ -131,11 +136,19 @@
             // thread in this process, set the message as a static reference so
             // after this call completes the same thread but in the interrogating
             // client can handle the message to generate the result.
-            if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
+            if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId
+                    && mHandler.hasAccessibilityCallback(message)) {
                 AccessibilityInteractionClient.getInstanceForThread(
                         interrogatingTid).setSameThreadMessage(message);
             } else {
-                mHandler.sendMessage(message);
+                // For messages without callback of interrogating client, just handle the
+                // message immediately if this is UI thread.
+                if (!mHandler.hasAccessibilityCallback(message)
+                        && Thread.currentThread().getId() == mMyLooperThreadId) {
+                    mHandler.handleMessage(message);
+                } else {
+                    mHandler.sendMessage(message);
+                }
             }
         }
     }
@@ -731,6 +744,52 @@
         }
     }
 
+    /**
+     * Finds the accessibility focused node in the root, and clears the accessibility focus.
+     */
+    public void clearAccessibilityFocusClientThread() {
+        final Message message = mHandler.obtainMessage();
+        message.what = PrivateHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS;
+
+        // Don't care about pid and tid because there's no interrogating client for this message.
+        scheduleMessage(message, 0, 0, CONSIDER_REQUEST_PREPARERS);
+    }
+
+    private void clearAccessibilityFocusUiThread() {
+        if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
+            return;
+        }
+        try {
+            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags =
+                    AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+            final View root = mViewRootImpl.mView;
+            if (root != null && isShown(root)) {
+                final View host = mViewRootImpl.mAccessibilityFocusedHost;
+                // If there is no accessibility focus host or it is not a descendant
+                // of the root from which to start the search, then the search failed.
+                if (host == null || !ViewRootImpl.isViewDescendantOf(host, root)) {
+                    return;
+                }
+                final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
+                final AccessibilityNodeInfo focusNode =
+                        mViewRootImpl.mAccessibilityFocusedVirtualView;
+                if (provider != null && focusNode != null) {
+                    final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
+                            focusNode.getSourceNodeId());
+                    provider.performAction(virtualNodeId,
+                            AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS.getId(),
+                            null);
+                } else {
+                    host.performAccessibilityAction(
+                            AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS.getId(),
+                            null);
+                }
+            }
+        } finally {
+            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+        }
+    }
+
     private View findViewByAccessibilityId(int accessibilityId) {
         View root = mViewRootImpl.mView;
         if (root == null) {
@@ -1294,6 +1353,12 @@
         private static final int MSG_APP_PREPARATION_FINISHED = 8;
         private static final int MSG_APP_PREPARATION_TIMEOUT = 9;
 
+        // Uses FIRST_NO_ACCESSIBILITY_CALLBACK_MSG for messages that don't need to call back
+        // results to interrogating client.
+        private static final int FIRST_NO_ACCESSIBILITY_CALLBACK_MSG = 100;
+        private static final int MSG_CLEAR_ACCESSIBILITY_FOCUS =
+                FIRST_NO_ACCESSIBILITY_CALLBACK_MSG + 1;
+
         public PrivateHandler(Looper looper) {
             super(looper);
         }
@@ -1320,6 +1385,8 @@
                     return "MSG_APP_PREPARATION_FINISHED";
                 case MSG_APP_PREPARATION_TIMEOUT:
                     return "MSG_APP_PREPARATION_TIMEOUT";
+                case MSG_CLEAR_ACCESSIBILITY_FOCUS:
+                    return "MSG_CLEAR_ACCESSIBILITY_FOCUS";
                 default:
                     throw new IllegalArgumentException("Unknown message type: " + type);
             }
@@ -1356,10 +1423,17 @@
                 case MSG_APP_PREPARATION_TIMEOUT: {
                     requestPreparerTimeoutUiThread();
                 } break;
+                case MSG_CLEAR_ACCESSIBILITY_FOCUS: {
+                    clearAccessibilityFocusUiThread();
+                } break;
                 default:
                     throw new IllegalArgumentException("Unknown message type: " + type);
             }
         }
+
+        boolean hasAccessibilityCallback(Message message) {
+            return message.what < FIRST_NO_ACCESSIBILITY_CALLBACK_MSG ? true : false;
+        }
     }
 
     private final class AddNodeInfosForViewId implements Predicate<View> {
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index 92e0009..ec79eea 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -16,10 +16,10 @@
 
 package android.view;
 
+import static android.view.Display.INVALID_DISPLAY;
+
 import android.graphics.Region;
 import android.os.IBinder;
-import android.view.IWindow;
-import android.view.InputChannel;
 
 /**
  * Functions as a handle for a window that can receive input.
@@ -94,6 +94,10 @@
     // Display this input is on.
     public int displayId;
 
+    // If this value is set to a valid display ID, it indicates this window is a portal which
+    // transports the touch of this window to the display indicated by portalToDisplayId.
+    public int portalToDisplayId = INVALID_DISPLAY;
+
     private native void nativeDispose();
 
     public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index dc7c343..6061cb2 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -399,10 +400,15 @@
     }
 
     private void initPrecompiledViews() {
-        // Check if precompiled layouts are enabled by a system property.
-        mUseCompiledView =
-            SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false);
+        initPrecompiledViews(
+                SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false));
+    }
+
+    private void initPrecompiledViews(boolean enablePrecompiledViews) {
+        mUseCompiledView = enablePrecompiledViews;
+
         if (!mUseCompiledView) {
+            mPrecompiledClassLoader = null;
             return;
         }
 
@@ -431,6 +437,17 @@
             }
             mUseCompiledView = false;
         }
+        if (!mUseCompiledView) {
+            mPrecompiledClassLoader = null;
+        }
+    }
+
+    /**
+     * @hide for use by CTS tests
+     */
+    @TestApi
+    public void setPrecompiledLayoutsEnabledForTesting(boolean enablePrecompiledLayouts) {
+        initPrecompiledViews(enablePrecompiledLayouts);
     }
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f47eb10..9213f32 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -8718,6 +8718,15 @@
                 }
             }
         }
+
+        @Override
+        public void clearAccessibilityFocus() {
+            ViewRootImpl viewRootImpl = mViewRootImpl.get();
+            if (viewRootImpl != null && viewRootImpl.mView != null) {
+                viewRootImpl.getAccessibilityInteractionController()
+                        .clearAccessibilityFocusClientThread();
+            }
+        }
     }
 
     private class SendWindowContentChangedAccessibilityEvent implements Runnable {
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 4c0fdfd..947ff05 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -55,4 +55,6 @@
     void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
         int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
         int interrogatingPid, long interrogatingTid);
+
+    void clearAccessibilityFocus();
 }
diff --git a/core/java/android/view/contentcapture/UserDataRemovalRequest.java b/core/java/android/view/contentcapture/UserDataRemovalRequest.java
index 8ee63ef..8fedcd5 100644
--- a/core/java/android/view/contentcapture/UserDataRemovalRequest.java
+++ b/core/java/android/view/contentcapture/UserDataRemovalRequest.java
@@ -16,7 +16,6 @@
 package android.view.contentcapture;
 
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.net.Uri;
 import android.os.Parcel;
@@ -67,9 +66,7 @@
 
     /**
      * Gets the name of the app that's making the request.
-     * @hide
      */
-    @SystemApi
     @NonNull
     public String getPackageName() {
         return mPackageName;
@@ -77,20 +74,14 @@
 
     /**
      * Checks if app is requesting to remove all user data associated with its package.
-     *
-     * @hide
      */
-    @SystemApi
     public boolean isForEverything() {
         return mForEverything;
     }
 
     /**
      * Gets the list of {@code Uri}s the apps is requesting to remove.
-     *
-     * @hide
      */
-    @SystemApi
     @NonNull
     public List<UriRequest> getUriRequests() {
         return mUriRequests;
@@ -203,9 +194,7 @@
 
     /**
      * Representation of a request to remove data associated with an {@link Uri}.
-     * @hide
      */
-    @SystemApi
     public final class UriRequest {
         private final @NonNull Uri mUri;
         private final boolean mRecursive;
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 5a56136..8a688d8 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -164,9 +164,10 @@
     TextClassifier NO_OP = new TextClassifier() {};
 
     /**
-     * Used as a boolean value to indicate the intent is generated by TextClassifier.
+     * Extra that is included on activity intents coming from a TextClassifier when
+     * it suggests actions to its caller.
      * <p>
-     * All {@link TextClassifier} implementations should set this boolean extra to be true in their
+     * All {@link TextClassifier} implementations should make sure this extra exists in their
      * generated intents.
      */
     String EXTRA_FROM_TEXT_CLASSIFIER = "android.view.textclassifier.extra.FROM_TEXT_CLASSIFIER";
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 299801a..46f42f7 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -24,6 +24,7 @@
 import android.app.prediction.AppTarget;
 import android.app.prediction.AppTargetEvent;
 import android.app.prediction.AppTargetId;
+import android.content.ClipData;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -41,9 +42,13 @@
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
 import android.database.DataSetObserver;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Path;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
+import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Environment;
@@ -62,7 +67,9 @@
 import android.service.chooser.IChooserTargetResult;
 import android.service.chooser.IChooserTargetService;
 import android.text.TextUtils;
+import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Size;
 import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -73,9 +80,11 @@
 import android.view.ViewGroup.LayoutParams;
 import android.widget.AbsListView;
 import android.widget.BaseAdapter;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.Space;
+import android.widget.TextView;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -85,6 +94,7 @@
 import com.google.android.collect.Lists;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -262,16 +272,31 @@
         }
 
         mReplacementExtras = intent.getBundleExtra(Intent.EXTRA_REPLACEMENT_EXTRAS);
-        CharSequence title = intent.getCharSequenceExtra(Intent.EXTRA_TITLE);
+
+        // Do not allow the title to be changed when sharing content
+        CharSequence title = null;
+        if (target != null) {
+            String targetAction = target.getAction();
+            if (!(Intent.ACTION_SEND.equals(targetAction) || Intent.ACTION_SEND_MULTIPLE.equals(
+                    targetAction))) {
+                title = intent.getCharSequenceExtra(Intent.EXTRA_TITLE);
+            } else {
+                Log.w(TAG, "Ignoring intent's EXTRA_TITLE, deprecated in P. You may wish to set a"
+                        + " preview title by using EXTRA_TITLE property of the wrapped"
+                        + " EXTRA_INTENT.");
+            }
+        }
+
         int defaultTitleRes = 0;
         if (title == null) {
             defaultTitleRes = com.android.internal.R.string.chooseActivity;
         }
+
         Parcelable[] pa = intent.getParcelableArrayExtra(Intent.EXTRA_INITIAL_INTENTS);
         Intent[] initialIntents = null;
         if (pa != null) {
             initialIntents = new Intent[pa.length];
-            for (int i=0; i<pa.length; i++) {
+            for (int i = 0; i < pa.length; i++) {
                 if (!(pa[i] instanceof Intent)) {
                     Log.w(TAG, "Initial intent #" + i + " not an Intent: " + pa[i]);
                     finish();
@@ -364,6 +389,68 @@
         }
     }
 
+    /**
+     * Override method to add content preview area, specific to the chooser activity.
+     */
+    @Override
+    public void setHeader() {
+        super.setHeader();
+
+        Intent targetIntent = getTargetIntent();
+        if (targetIntent == null) {
+            return;
+        }
+
+        ViewGroup contentPreviewLayout = findViewById(R.id.content_preview);
+        String action = targetIntent.getAction();
+        if (!(Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action))) {
+            contentPreviewLayout.setVisibility(View.GONE);
+            return;
+        }
+
+        showDefaultContentPreview(contentPreviewLayout, targetIntent);
+    }
+
+    private void showDefaultContentPreview(final ViewGroup parentLayout,
+            final Intent targetIntent) {
+        CharSequence sharingText = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT);
+        TextView previewTextView = findViewById(R.id.content_preview_text);
+        if (sharingText == null) {
+            previewTextView.setVisibility(View.GONE);
+        } else {
+            previewTextView.setText(sharingText);
+        }
+
+        String previewTitle = targetIntent.getStringExtra(Intent.EXTRA_TITLE);
+        TextView previewTitleView = findViewById(R.id.content_preview_title);
+        if (previewTitle == null) {
+            previewTitleView.setVisibility(View.GONE);
+        } else {
+            previewTitleView.setText(previewTitle);
+        }
+
+        ClipData previewData = targetIntent.getClipData();
+        Uri previewThumbnail = null;
+        if (previewData != null) {
+            if (previewData.getItemCount() > 0) {
+                ClipData.Item previewDataItem = previewData.getItemAt(0);
+                previewThumbnail = previewDataItem.getUri();
+            }
+        }
+
+        ImageView previewThumbnailView = findViewById(R.id.content_preview_thumbnail);
+        if (previewThumbnail == null) {
+            previewThumbnailView.setVisibility(View.GONE);
+        } else {
+            Bitmap bmp = loadThumbnail(previewThumbnail, new Size(200, 200));
+            if (bmp == null) {
+                previewThumbnailView.setVisibility(View.GONE);
+            } else {
+                previewThumbnailView.setImageBitmap(bmp);
+            }
+        }
+    }
+
     static SharedPreferences getPinnedSharedPrefs(Context context) {
         // The code below is because in the android:ui process, no one can hear you scream.
         // The package info in the context isn't initialized in the way it is for normal apps,
@@ -630,15 +717,19 @@
                 }
             }
             if (targetsToQuery >= QUERY_TARGET_SERVICE_LIMIT) {
-                if (DEBUG) Log.d(TAG, "queryTargets hit query target limit "
-                        + QUERY_TARGET_SERVICE_LIMIT);
+                if (DEBUG) {
+                    Log.d(TAG, "queryTargets hit query target limit "
+                            + QUERY_TARGET_SERVICE_LIMIT);
+                }
                 break;
             }
         }
 
         if (!mServiceConnections.isEmpty()) {
-            if (DEBUG) Log.d(TAG, "queryTargets setting watchdog timer for "
-                    + WATCHDOG_TIMEOUT_MILLIS + "ms");
+            if (DEBUG) {
+                Log.d(TAG, "queryTargets setting watchdog timer for "
+                        + WATCHDOG_TIMEOUT_MILLIS + "ms");
+            }
             mChooserHandler.sendEmptyMessageDelayed(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT,
                     WATCHDOG_TIMEOUT_MILLIS);
         } else {
@@ -969,6 +1060,20 @@
                 mLaunchedFromUid);
     }
 
+    @VisibleForTesting
+    protected Bitmap loadThumbnail(Uri uri, Size size) {
+        if (uri == null || size == null) {
+            return null;
+        }
+
+        try {
+            return getContentResolver().loadThumbnail(uri, size, null);
+        } catch (IOException | NullPointerException ex) {
+            Log.w(TAG, "Error loading preview thumbnail for uri: " + uri.toString(), ex);
+        }
+        return null;
+    }
+
     final class ChooserTargetInfo implements TargetInfo {
         private final DisplayResolveInfo mSourceInfo;
         private final ResolveInfo mBackupResolveInfo;
@@ -1247,7 +1352,7 @@
                     UserManager userManager =
                             (UserManager) getSystemService(Context.USER_SERVICE);
                     if (ii instanceof LabeledIntent) {
-                        LabeledIntent li = (LabeledIntent)ii;
+                        LabeledIntent li = (LabeledIntent) ii;
                         ri.resolvePackageName = li.getSourcePackage();
                         ri.labelRes = li.getLabelResource();
                         ri.nonLocalizedLabel = li.getNonLocalizedLabel();
@@ -1391,8 +1496,10 @@
         }
 
         public void addServiceResults(DisplayResolveInfo origTarget, List<ChooserTarget> targets) {
-            if (DEBUG) Log.d(TAG, "addServiceResults " + origTarget + ", " + targets.size()
-                    + " targets");
+            if (DEBUG) {
+                Log.d(TAG, "addServiceResults " + origTarget + ", " + targets.size()
+                        + " targets");
+            }
 
             if (mTargetsNeedPruning && targets.size() > 0) {
                 // First proper update since we got an onListRebuilt() with (transient) 0 items.
@@ -1492,8 +1599,9 @@
         public int getCount() {
             return (int) (
                     getCallerTargetRowCount()
-                    + getServiceTargetRowCount()
-                    + Math.ceil((float) mChooserListAdapter.getStandardTargetCount() / mColumnCount)
+                            + getServiceTargetRowCount()
+                            + Math.ceil(
+                            (float) mChooserListAdapter.getStandardTargetCount() / mColumnCount)
             );
         }
 
@@ -1860,7 +1968,7 @@
 
             final int chooserTargetRows = mChooserRowAdapter.getServiceTargetRowCount();
             int offset = 0;
-            for (int i = 0; i < chooserTargetRows; i++)  {
+            for (int i = 0; i < chooserTargetRows; i++) {
                 final int pos = mChooserRowAdapter.getCallerTargetRowCount() + i;
                 final int vt = mChooserRowAdapter.getItemViewType(pos);
                 if (vt != mCachedViewType) {
@@ -1882,4 +1990,65 @@
             mResolverDrawerLayout.setCollapsibleHeightReserved(offset);
         }
     }
+
+
+    /**
+     * Used internally to round image corners while obeying view padding.
+     */
+    public static class RoundedRectImageView extends ImageView {
+        private int mRadius = 0;
+        private Path mPath = new Path();
+
+        public RoundedRectImageView(Context context) {
+            super(context);
+        }
+
+        public RoundedRectImageView(Context context, AttributeSet attrs) {
+            this(context, attrs, 0);
+        }
+
+        public RoundedRectImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+            this(context, attrs, defStyleAttr, 0);
+        }
+
+        public RoundedRectImageView(Context context, AttributeSet attrs, int defStyleAttr,
+                int defStyleRes) {
+            super(context, attrs, defStyleAttr, defStyleRes);
+            mRadius = context.getResources().getDimensionPixelSize(R.dimen.chooser_corner_radius);
+        }
+
+        private void updatePath(int width, int height) {
+            mPath.reset();
+
+            int imageWidth = width - getPaddingLeft() - getPaddingRight();
+            int imageHeight = height - getPaddingTop() - getPaddingBottom();
+            mPath.addRoundRect(getPaddingLeft(), getPaddingTop(), imageWidth, imageHeight, mRadius,
+                    mRadius, Path.Direction.CW);
+        }
+
+        /**
+          * Sets the corner radius on all corners
+          *
+          * param radius 0 for no radius, &gt; 0 for a visible corner radius
+          */
+        public void setRadius(int radius) {
+            mRadius = radius;
+            updatePath(getWidth(), getHeight());
+        }
+
+        @Override
+        protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
+            super.onSizeChanged(width, height, oldWidth, oldHeight);
+            updatePath(width, height);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            if (mRadius != 0) {
+                canvas.clipPath(mPath);
+            }
+
+            super.onDraw(canvas);
+        }
+    }
 }
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index a50c736..0919911 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1044,7 +1044,10 @@
         }
     }
 
-    public void setTitleAndIcon() {
+    /**
+     * Configure the area above the app selection list (title, content preview, etc).
+     */
+    public void setHeader() {
         if (mAdapter.getCount() == 0 && mAdapter.mPlaceholderCount == 0) {
             final TextView titleView = findViewById(R.id.title);
             if (titleView != null) {
@@ -1062,23 +1065,6 @@
                 titleView.setText(title);
             }
             setTitle(title);
-
-            // Try to initialize the title icon if we have a view for it and a title to match
-            final ImageView titleIcon = findViewById(R.id.title_icon);
-            if (titleIcon != null) {
-                ApplicationInfo ai = null;
-                try {
-                    if (!TextUtils.isEmpty(mReferrerPackage)) {
-                        ai = mPm.getApplicationInfo(mReferrerPackage, 0);
-                    }
-                } catch (NameNotFoundException e) {
-                    Log.e(TAG, "Could not find referrer package " + mReferrerPackage);
-                }
-
-                if (ai != null) {
-                    titleIcon.setImageDrawable(ai.loadIcon(mPm));
-                }
-            }
         }
 
         final ImageView iconView = findViewById(R.id.icon);
@@ -1692,7 +1678,7 @@
                 mPostListReadyRunnable = new Runnable() {
                     @Override
                     public void run() {
-                        setTitleAndIcon();
+                        setHeader();
                         resetButtonBar();
                         onListRebuilt();
                         mPostListReadyRunnable = null;
diff --git a/core/java/com/android/internal/os/AppZygoteInit.java b/core/java/com/android/internal/os/AppZygoteInit.java
index afe6dad..6ba584d 100644
--- a/core/java/com/android/internal/os/AppZygoteInit.java
+++ b/core/java/com/android/internal/os/AppZygoteInit.java
@@ -73,6 +73,9 @@
             Log.i(TAG, "Beginning application preload for " + appInfo.packageName);
             LoadedApk loadedApk = new LoadedApk(null, appInfo, null, null, false, true, false);
             ClassLoader loader = loadedApk.getClassLoader();
+
+            Zygote.allowAppFilesAcrossFork(appInfo);
+
             Class<?> cl;
             Method m;
             try {
diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java
index c8d30b2..9ed7384 100644
--- a/core/java/com/android/internal/os/WebViewZygoteInit.java
+++ b/core/java/com/android/internal/os/WebViewZygoteInit.java
@@ -78,18 +78,7 @@
             ClassLoader loader = loadedApk.getClassLoader();
             doPreload(loader, WebViewFactory.getWebViewLibrary(appInfo));
 
-            // Add the APK to the Zygote's list of allowed files for children.
-            Zygote.nativeAllowFileAcrossFork(appInfo.sourceDir);
-            if (appInfo.splitSourceDirs != null) {
-                for (String path : appInfo.splitSourceDirs) {
-                    Zygote.nativeAllowFileAcrossFork(path);
-                }
-            }
-            if (appInfo.sharedLibraryFiles != null) {
-                for (String path : appInfo.sharedLibraryFiles) {
-                    Zygote.nativeAllowFileAcrossFork(path);
-                }
-            }
+            Zygote.allowAppFilesAcrossFork(appInfo);
 
             Log.i(TAG, "Application preload done");
         }
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index bc7cf87..474d4d7 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -20,6 +20,7 @@
 
 import static com.android.internal.os.ZygoteConnectionConstants.MAX_ZYGOTE_ARGC;
 
+import android.content.pm.ApplicationInfo;
 import android.net.Credentials;
 import android.net.LocalServerSocket;
 import android.net.LocalSocket;
@@ -370,6 +371,27 @@
     protected static native void nativeAllowFileAcrossFork(String path);
 
     /**
+     * Lets children of the zygote inherit open file descriptors that belong to the
+     * ApplicationInfo that is passed in.
+     *
+     * @param appInfo ApplicationInfo of the application
+     */
+    protected static void allowAppFilesAcrossFork(ApplicationInfo appInfo) {
+        Zygote.nativeAllowFileAcrossFork(appInfo.sourceDir);
+        if (appInfo.splitSourceDirs != null) {
+            for (String path : appInfo.splitSourceDirs) {
+                Zygote.nativeAllowFileAcrossFork(path);
+            }
+        }
+        // As well as its shared libs
+        if (appInfo.sharedLibraryFiles != null) {
+            for (String path : appInfo.sharedLibraryFiles) {
+                Zygote.nativeAllowFileAcrossFork(path);
+            }
+        }
+    }
+
+    /**
      * Installs a seccomp filter that limits setresuid()/setresgid() to the passed-in range
      * @param uidGidMin The smallest allowed uid/gid
      * @param uidGidMax The largest allowed uid/gid
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index c0e45b1..67a7441 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -55,6 +55,7 @@
     jfieldID ownerUid;
     jfieldID inputFeatures;
     jfieldID displayId;
+    jfieldID portalToDisplayId;
 } gInputWindowHandleClassInfo;
 
 static Mutex gHandleMutex;
@@ -154,6 +155,8 @@
             gInputWindowHandleClassInfo.inputFeatures);
     mInfo.displayId = env->GetIntField(obj,
             gInputWindowHandleClassInfo.displayId);
+    mInfo.portalToDisplayId = env->GetIntField(obj,
+            gInputWindowHandleClassInfo.portalToDisplayId);
 
     jobject inputApplicationHandleObj = env->GetObjectField(obj,
             gInputWindowHandleClassInfo.inputApplicationHandle);
@@ -307,6 +310,9 @@
 
     GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz,
             "displayId", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.portalToDisplayId, clazz,
+            "portalToDisplayId", "I");
     return 0;
 }
 
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index e0eaf14..a160451 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -230,8 +230,6 @@
     }
     optional Connectivity connectivity = 32;
 
-    reserved 145; // Used to be ContentCapture, which moved to DeviceConfig
-
     optional SettingProto contact_metadata_sync_enabled = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto contacts_database_wal_enabled = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
@@ -999,7 +997,7 @@
         optional SettingProto watchdog_poor_network_test_enabled = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto suspend_optimizations_enabled = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto verbose_logging_enabled = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
-        optional SettingProto connected_mac_randomization_enabled = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        reserved 25; // connected_mac_randomization_enabled
         optional SettingProto max_dhcp_retry_count = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto mobile_data_transition_wakelock_timeout_ms = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
         // Controls whether WiFi configurations created by a Device Owner app should
@@ -1039,5 +1037,5 @@
 
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 149;
+    // Next tag = 145 then 149; // (145 was removed)
 }
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index ded2b35..c42f43a 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -29,8 +29,6 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_alwaysShow="true"
-            android:elevation="8dp"
-            android:paddingStart="16dp"
             android:background="?attr/colorBackgroundFloating" >
         <TextView android:id="@+id/profile_button"
                   android:layout_width="wrap_content"
@@ -46,25 +44,66 @@
                   android:layout_alignParentTop="true"
                   android:layout_alignParentRight="true"
                   android:singleLine="true"/>
-        <ImageView android:id="@+id/title_icon"
-                   android:layout_width="24dp"
-                   android:layout_height="24dp"
-                   android:layout_marginEnd="16dp"
-                   android:visibility="gone"
-                   android:scaleType="fitCenter"
-                   android:layout_below="@id/profile_button"
-                   android:layout_alignParentLeft="true"/>
+
         <TextView android:id="@+id/title"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
                   android:textAppearance="?attr/textAppearanceMedium"
-                  android:textSize="14sp"
-                  android:gravity="start|center_vertical"
+                  android:textSize="20sp"
+                  android:gravity="center"
                   android:paddingEnd="?attr/dialogPreferredPadding"
                   android:paddingTop="12dp"
-                  android:paddingBottom="12dp"
+                  android:paddingBottom="6dp"
                   android:layout_below="@id/profile_button"
-                  android:layout_toRightOf="@id/title_icon"/>
+                  android:layout_centerHorizontal="true"/>
+    </RelativeLayout>
+
+    <RelativeLayout 
+        android:id="@+id/content_preview"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="?attr/colorBackgroundFloating">
+      
+      <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
+            android:id="@+id/content_preview_thumbnail"
+            android:layout_alignParentTop="true"
+            android:layout_width="100dp"
+            android:layout_height="wrap_content"
+            android:layout_alignParentStart="true"
+            android:gravity="center"
+            android:adjustViewBounds="true"
+            android:maxWidth="90dp"
+            android:maxHeight="90dp"
+            android:scaleType="fitCenter"
+            android:padding="5dp"/>
+
+      <TextView
+          android:id="@+id/content_preview_title"
+          android:layout_alignParentTop="true"
+          android:layout_toEndOf="@id/content_preview_thumbnail"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:gravity="start|top"
+          android:textAppearance="?attr/textAppearanceMedium"
+          android:maxLines="2"
+          android:ellipsize="end"
+          android:paddingStart="15dp"
+          android:paddingEnd="15dp"
+          android:paddingTop="10dp" />
+
+      <TextView
+          android:id="@+id/content_preview_text"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:layout_below="@id/content_preview_title"
+          android:layout_toEndOf="@id/content_preview_thumbnail"
+          android:gravity="start|top"
+          android:maxLines="2"
+          android:ellipsize="end"
+          android:paddingStart="15dp"
+          android:paddingEnd="15dp"
+          android:paddingTop="10dp"
+          android:paddingBottom="5dp"/>
     </RelativeLayout>
 
     <ListView
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index c870683..ef3834c 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -714,4 +714,7 @@
     <dimen name="harmful_app_message_padding_bottom">24dp</dimen>
     <!-- Line spacing modifier for the message field of the harmful app dialog -->
     <item name="harmful_app_message_line_spacing_modifier" type="dimen">1.22</item>
+
+    <!-- chooser corner radius -->
+    <dimen name="chooser_corner_radius">4dp</dimen>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a761baf..6adb4a7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3082,7 +3082,7 @@
     <!-- Label for a link to a intent resolver dialog when selecting an editor application -->
     <string name="whichEditApplicationLabel">Edit</string>
     <!-- Title of intent resolver dialog when selecting a sharing application to run. -->
-    <string name="whichSendApplication">Share with</string>
+    <string name="whichSendApplication">Share</string>
     <!-- Title of intent resolver dialog when selecting a sharing application to run
          and a previously used application is known. -->
     <string name="whichSendApplicationNamed">Share with %1$s</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ca8e226..54a3243 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -50,6 +50,10 @@
   <java-symbol type="id" name="characterPicker" />
   <java-symbol type="id" name="clearDefaultHint" />
   <java-symbol type="id" name="contentPanel" />
+  <java-symbol type="id" name="content_preview" />
+  <java-symbol type="id" name="content_preview_thumbnail" />
+  <java-symbol type="id" name="content_preview_text" />
+  <java-symbol type="id" name="content_preview_title" />
   <java-symbol type="id" name="current_scene" />
   <java-symbol type="id" name="scene_layoutid_cache" />
   <java-symbol type="id" name="customPanel" />
@@ -2703,9 +2707,9 @@
   <java-symbol type="layout" name="date_picker_month_item_material" />
   <java-symbol type="id" name="month_view" />
   <java-symbol type="integer" name="config_zen_repeat_callers_threshold" />
+  <java-symbol type="dimen" name="chooser_corner_radius" />
   <java-symbol type="layout" name="chooser_grid" />
   <java-symbol type="layout" name="resolve_grid_item" />
-  <java-symbol type="id" name="title_icon" />
   <java-symbol type="id" name="day_picker_view_pager" />
   <java-symbol type="layout" name="day_picker_content_material" />
   <java-symbol type="drawable" name="scroll_indicator_material" />
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 9d04e63..6a81050 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -37,7 +37,9 @@
     mockwebserver \
     guava \
     androidx.test.runner \
+    androidx.test.ext.junit \
     androidx.test.rules \
+    androidx.test.espresso.core \
     mockito-target-minus-junit4 \
     espresso-core \
     ub-uiautomator \
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 86818c6..268bb81 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -62,6 +62,7 @@
     <uses-permission android:name="android.permission.READ_LOGS"/>
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.READ_SMS"/>
+    <uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
     <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
@@ -1144,6 +1145,14 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.view.accessibility.AccessibilityTestActivity"
+                  android:label="AccessibilityTestActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <!-- Activity-level metadata -->
         <meta-data android:name="com.android.frameworks.coretests.isApp" android:value="true" />
         <meta-data android:name="com.android.frameworks.coretests.string" android:value="foo" />
diff --git a/core/tests/coretests/res/layout/accessibility_test.xml b/core/tests/coretests/res/layout/accessibility_test.xml
new file mode 100644
index 0000000..1bdd21b
--- /dev/null
+++ b/core/tests/coretests/res/layout/accessibility_test.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <Button android:id="@+id/appNameBtn"
+        android:text="@string/app_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginRight="60dp"
+        android:bufferType="normal">
+    </Button>
+</LinearLayout>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 0b5bde7..e32b412 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -509,7 +509,6 @@
                     Settings.Global.WIFI_ALWAYS_REQUESTED,
                     Settings.Global.WIFI_BADGING_THRESHOLDS,
                     Settings.Global.WIFI_BOUNCE_DELAY_OVERRIDE_MS,
-                    Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED,
                     Settings.Global.WIFI_COUNTRY_CODE,
                     Settings.Global.WIFI_DATA_STALL_MIN_TX_BAD,
                     Settings.Global.WIFI_DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX,
diff --git a/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java b/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java
new file mode 100644
index 0000000..d0719cb
--- /dev/null
+++ b/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2018 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.view;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.Service;
+import android.app.UiAutomation;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityTestActivity;
+import android.view.accessibility.AccessibilityWindowInfo;
+
+import com.android.compatibility.common.util.TestUtils;
+import com.android.frameworks.coretests.R;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class AccessibilityInteractionControllerTest {
+    static final long TIMEOUT_DEFAULT = 10000; // 10 seconds
+
+    private static Instrumentation sInstrumentation;
+    private static UiAutomation sUiAutomation;
+
+    @Rule
+    public ActivityTestRule<AccessibilityTestActivity> mActivityRule = new ActivityTestRule<>(
+            AccessibilityTestActivity.class, false, false);
+
+    private AccessibilityInteractionController mAccessibilityInteractionController;
+    private ViewRootImpl mViewRootImpl;
+    private View mButton;
+
+    @BeforeClass
+    public static void oneTimeSetup() {
+        sInstrumentation = InstrumentationRegistry.getInstrumentation();
+        sUiAutomation = sInstrumentation.getUiAutomation();
+    }
+
+    @AfterClass
+    public static void postTestTearDown() {
+        sUiAutomation.destroy();
+    }
+
+    @Before
+    public void setUp() throws Throwable {
+        launchActivity();
+        enableTouchExploration(true);
+        mActivityRule.runOnUiThread(() -> {
+            mViewRootImpl = mActivityRule.getActivity().getWindow().getDecorView()
+                    .getViewRootImpl();
+            mButton = mActivityRule.getActivity().findViewById(R.id.appNameBtn);
+        });
+        mAccessibilityInteractionController =
+                mViewRootImpl.getAccessibilityInteractionController();
+    }
+
+    @After
+    public void tearDown() {
+        enableTouchExploration(false);
+    }
+
+    @Test
+    public void clearAccessibilityFocus_shouldClearFocus() throws Exception {
+        performAccessibilityFocus("com.android.frameworks.coretests:id/appNameBtn");
+        assertTrue("Button should have a11y focus",
+                mButton.isAccessibilityFocused());
+        mAccessibilityInteractionController.clearAccessibilityFocusClientThread();
+        sInstrumentation.waitForIdleSync();
+        assertFalse("Button should not have a11y focus",
+                mButton.isAccessibilityFocused());
+    }
+
+    @Test
+    public void clearAccessibilityFocus_uiThread_shouldClearFocus() throws Exception {
+        performAccessibilityFocus("com.android.frameworks.coretests:id/appNameBtn");
+        assertTrue("Button should have a11y focus",
+                mButton.isAccessibilityFocused());
+        sInstrumentation.runOnMainSync(() -> {
+            mAccessibilityInteractionController.clearAccessibilityFocusClientThread();
+        });
+        assertFalse("Button should not have a11y focus",
+                mButton.isAccessibilityFocused());
+    }
+
+    private void launchActivity() {
+        final Object waitObject = new Object();
+        final int[] location = new int[2];
+        final StringBuilder activityPackage = new StringBuilder();
+        final Rect bounds = new Rect();
+        final StringBuilder activityTitle = new StringBuilder();
+        try {
+            final long executionStartTimeMillis = SystemClock.uptimeMillis();
+            sUiAutomation.setOnAccessibilityEventListener((event) -> {
+                if (event.getEventTime() < executionStartTimeMillis) {
+                    return;
+                }
+                synchronized (waitObject) {
+                    waitObject.notifyAll();
+                }
+            });
+            enableRetrieveAccessibilityWindows();
+
+            final Activity activity = mActivityRule.launchActivity(null);
+            sInstrumentation.runOnMainSync(() -> {
+                activity.getWindow().getDecorView().getLocationOnScreen(location);
+                activityPackage.append(activity.getPackageName());
+                activityTitle.append(activity.getTitle());
+            });
+            sInstrumentation.waitForIdleSync();
+
+            TestUtils.waitOn(waitObject, () -> {
+                final AccessibilityWindowInfo window = findWindowByTitle(activityTitle);
+                if (window == null) return false;
+                window.getBoundsInScreen(bounds);
+                activity.getWindow().getDecorView().getLocationOnScreen(location);
+                if (bounds.isEmpty()) {
+                    return false;
+                }
+                return (!bounds.isEmpty())
+                        && (bounds.left == location[0]) && (bounds.top == location[1]);
+            }, TIMEOUT_DEFAULT, "Launch Activity");
+        } finally {
+            sUiAutomation.setOnAccessibilityEventListener(null);
+        }
+    }
+
+    private void enableRetrieveAccessibilityWindows() {
+        AccessibilityServiceInfo info = sUiAutomation.getServiceInfo();
+        info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+        sUiAutomation.setServiceInfo(info);
+    }
+
+    private void enableTouchExploration(boolean enabled) {
+        final Object waitObject = new Object();
+        final AccessibilityManager accessibilityManager =
+                (AccessibilityManager) sInstrumentation.getContext().getSystemService(
+                        Service.ACCESSIBILITY_SERVICE);
+        final AccessibilityManager.TouchExplorationStateChangeListener listener = status -> {
+            synchronized (waitObject) {
+                waitObject.notifyAll();
+            }
+        };
+        try {
+            accessibilityManager.addTouchExplorationStateChangeListener(listener);
+            final AccessibilityServiceInfo info = sUiAutomation.getServiceInfo();
+            if (enabled) {
+                info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+            } else {
+                info.flags &= ~AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+            }
+            sUiAutomation.setServiceInfo(info);
+            TestUtils.waitOn(waitObject,
+                    () -> accessibilityManager.isTouchExplorationEnabled() == enabled,
+                    TIMEOUT_DEFAULT,
+                    (enabled ? "Enable" : "Disable") + "touch exploration");
+        } finally {
+            accessibilityManager.removeTouchExplorationStateChangeListener(listener);
+        }
+    }
+
+    private void performAccessibilityFocus(String viewId) throws TimeoutException {
+        final AccessibilityNodeInfo node = sUiAutomation.getRootInActiveWindow()
+                .findAccessibilityNodeInfosByViewId(viewId).get(0);
+        // Perform an action and wait for an event
+        sUiAutomation.executeAndWaitForEvent(
+                () -> node.performAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS),
+                event -> event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED,
+                TIMEOUT_DEFAULT);
+        node.refresh();
+    }
+
+    private AccessibilityWindowInfo findWindowByTitle(CharSequence title) {
+        final List<AccessibilityWindowInfo> windows = sUiAutomation.getWindows();
+        AccessibilityWindowInfo returnValue = null;
+        for (int i = 0; i < windows.size(); i++) {
+            final AccessibilityWindowInfo window = windows.get(i);
+            if (TextUtils.equals(title, window.getTitle())) {
+                returnValue = window;
+            } else {
+                window.recycle();
+            }
+        }
+        return returnValue;
+    }
+}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityTestActivity.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityTestActivity.java
new file mode 100644
index 0000000..a17fa73
--- /dev/null
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityTestActivity.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 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.view.accessibility;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
+
+/**
+ * An activity for accessibility test.
+ */
+public class AccessibilityTestActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        turnOnScreen();
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.accessibility_test);
+    }
+
+    private void turnOnScreen() {
+        setTurnScreenOn(true);
+        setShowWhenLocked(true);
+        KeyguardManager keyguardManager = (KeyguardManager) getSystemService(
+                Context.KEYGUARD_SERVICE);
+        keyguardManager.requestDismissKeyguard(this, null);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index aaa624e..21fcae7 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -16,12 +16,12 @@
 
 package com.android.internal.app;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
 
@@ -33,12 +33,18 @@
 import static org.mockito.Mockito.when;
 
 import android.app.usage.UsageStatsManager;
+import android.content.ClipData;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.net.Uri;
 
-import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.R;
 import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
@@ -69,7 +75,21 @@
 
     @Test
     public void customTitle() throws InterruptedException {
-        Intent sendIntent = createSendImageIntent();
+        Intent viewIntent = createViewTextIntent();
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+        mActivityRule.launchActivity(Intent.createChooser(viewIntent, "chooser test"));
+
+        waitForIdle();
+        onView(withId(R.id.title)).check(matches(withText("chooser test")));
+    }
+
+    @Test
+    public void customTitleIgnoredForSendIntents() throws InterruptedException {
+        Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
 
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
@@ -77,12 +97,12 @@
                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
         mActivityRule.launchActivity(Intent.createChooser(sendIntent, "chooser test"));
         waitForIdle();
-        onView(withId(R.id.title)).check(matches(withText("chooser test")));
+        onView(withId(R.id.title)).check(matches(withText(R.string.whichSendApplication)));
     }
 
     @Test
     public void emptyTitle() throws InterruptedException {
-        Intent sendIntent = createSendImageIntent();
+        Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
 
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
@@ -95,8 +115,72 @@
     }
 
     @Test
+    public void emptyPreviewTitleAndThumbnail() throws InterruptedException {
+        Intent sendIntent = createSendTextIntentWithPreview(null, null);
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+        mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
+        waitForIdle();
+        onView(withId(R.id.content_preview_title)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void visiblePreviewTitleWithoutThumbnail() throws InterruptedException {
+        String previewTitle = "My Content Preview Title";
+        Intent sendIntent = createSendTextIntentWithPreview(previewTitle, null);
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+        mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
+        waitForIdle();
+        onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
+        onView(withId(R.id.content_preview_title)).check(matches(withText(previewTitle)));
+        onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void visiblePreviewTitleWithInvalidThumbnail() throws InterruptedException {
+        String previewTitle = "My Content Preview Title";
+        Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
+                Uri.parse("tel:(+49)12345789"));
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+        mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
+        waitForIdle();
+        onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
+        onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void visiblePreviewTitleAndThumbnail() throws InterruptedException {
+        String previewTitle = "My Content Preview Title";
+        Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
+                Uri.parse("android.resource://com.android.frameworks.coretests/"
+                        + com.android.frameworks.coretests.R.drawable.test320x240));
+        sOverrides.previewThumbnail = createBitmap();
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+        mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
+        waitForIdle();
+        onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
+        onView(withId(R.id.content_preview_thumbnail)).check(matches(isDisplayed()));
+    }
+
+    @Test
     public void twoOptionsAndUserSelectsOne() throws InterruptedException {
-        Intent sendIntent = createSendImageIntent();
+        Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
 
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
@@ -125,7 +209,7 @@
 
     @Test
     public void updateChooserCountsAndModelAfterUserSelection() throws InterruptedException {
-        Intent sendIntent = createSendImageIntent();
+        Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
 
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
@@ -158,7 +242,7 @@
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class))).thenReturn(null);
-        Intent sendIntent = createSendImageIntent();
+        Intent sendIntent = createSendTextIntent();
         final ChooserWrapperActivity activity = mActivityRule
                 .launchActivity(Intent.createChooser(sendIntent, null));
         waitForIdle();
@@ -186,7 +270,7 @@
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
 
-        Intent sendIntent = createSendImageIntent();
+        Intent sendIntent = createSendTextIntent();
         final ChooserWrapperActivity activity = mActivityRule
                 .launchActivity(Intent.createChooser(sendIntent, null));
         waitForIdle();
@@ -197,7 +281,7 @@
 
     @Test
     public void hasOtherProfileOneOption() throws Exception {
-        Intent sendIntent = createSendImageIntent();
+        Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos =
                 createResolvedComponentsForTestWithOtherProfile(2);
         ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
@@ -234,7 +318,7 @@
 
     @Test
     public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
-        Intent sendIntent = createSendImageIntent();
+        Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos =
                 createResolvedComponentsForTestWithOtherProfile(3);
         ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
@@ -273,7 +357,7 @@
 
     @Test
     public void hasLastChosenActivityAndOtherProfile() throws Exception {
-        Intent sendIntent = createSendImageIntent();
+        Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos =
                 createResolvedComponentsForTestWithOtherProfile(3);
         ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
@@ -308,14 +392,33 @@
         assertThat(chosen[0], is(toChoose));
     }
 
-    private Intent createSendImageIntent() {
+    private Intent createSendTextIntent() {
         Intent sendIntent = new Intent();
         sendIntent.setAction(Intent.ACTION_SEND);
         sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
-        sendIntent.setType("image/jpeg");
         return sendIntent;
     }
 
+    private Intent createSendTextIntentWithPreview(String title, Uri imageThumbnail) {
+        Intent sendIntent = new Intent();
+        sendIntent.setAction(Intent.ACTION_SEND);
+        sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
+        sendIntent.putExtra(Intent.EXTRA_TITLE, title);
+        if (imageThumbnail != null) {
+            ClipData.Item clipItem = new ClipData.Item(imageThumbnail);
+            sendIntent.setClipData(new ClipData("Clip Label", new String[]{"image/png"}, clipItem));
+        }
+
+        return sendIntent;
+    }
+
+    private Intent createViewTextIntent() {
+        Intent viewIntent = new Intent();
+        viewIntent.setAction(Intent.ACTION_VIEW);
+        viewIntent.putExtra(Intent.EXTRA_TEXT, "testing intent viewing");
+        return viewIntent;
+    }
+
     private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
         for (int i = 0; i < numberOfResults; i++) {
@@ -340,4 +443,24 @@
     private void waitForIdle() {
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
-}
\ No newline at end of file
+
+    private Bitmap createBitmap() {
+        int width = 200;
+        int height = 200;
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+
+        Paint paint = new Paint();
+        paint.setColor(Color.RED);
+        paint.setStyle(Paint.Style.FILL);
+        canvas.drawPaint(paint);
+
+        paint.setColor(Color.WHITE);
+        paint.setAntiAlias(true);
+        paint.setTextSize(14.f);
+        paint.setTextAlign(Paint.Align.CENTER);
+        canvas.drawText("Hi!", (width / 2.f), (height / 2.f), paint);
+
+        return bitmap;
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 60529f6..637d2ea 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -21,6 +21,9 @@
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.util.Size;
 
 import java.util.function.Function;
 
@@ -74,6 +77,14 @@
         return super.getPackageManager();
     }
 
+    @Override
+    protected Bitmap loadThumbnail(Uri uri, Size size) {
+        if (sOverrides.previewThumbnail != null) {
+            return sOverrides.previewThumbnail;
+        }
+        return super.loadThumbnail(uri, size);
+    }
+
     /**
      * We cannot directly mock the activity created since instrumentation creates it.
      * <p>
@@ -85,11 +96,13 @@
         public Function<TargetInfo, Boolean> onSafelyStartCallback;
         public ResolverListController resolverListController;
         public Boolean isVoiceInteraction;
+        public Bitmap previewThumbnail;
 
         public void reset() {
             onSafelyStartCallback = null;
             isVoiceInteraction = null;
             createPackageManager = null;
+            previewThumbnail = null;
             resolverListController = mock(ResolverListController.class);
         }
     }
diff --git a/libs/hwui/private/hwui/DrawVkInfo.h b/libs/hwui/private/hwui/DrawVkInfo.h
index abc4dbf..fb55f5c 100644
--- a/libs/hwui/private/hwui/DrawVkInfo.h
+++ b/libs/hwui/private/hwui/DrawVkInfo.h
@@ -29,7 +29,7 @@
   VkDevice device;
   VkQueue queue;
   uint32_t graphics_queue_index;
-  uint32_t instance_version;
+  uint32_t api_version;
   const char* const* enabled_instance_extension_names;
   uint32_t enabled_instance_extension_names_length;
   const char* const* enabled_device_extension_names;
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 1e75202..582d51e 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -83,7 +83,6 @@
     mDevice = VK_NULL_HANDLE;
     mPhysicalDevice = VK_NULL_HANDLE;
     mInstance = VK_NULL_HANDLE;
-    mInstanceVersion = 0u;
     mInstanceExtensions.clear();
     mDeviceExtensions.clear();
     free_features_extensions_structs(mPhysicalDeviceFeatures2);
@@ -100,7 +99,7 @@
         0,                                  // applicationVersion
         "android framework",                // pEngineName
         0,                                  // engineVerison
-        VK_MAKE_VERSION(1, 1, 0),           // apiVersion
+        mAPIVersion,                        // apiVersion
     };
 
     {
@@ -377,8 +376,9 @@
     }
 
     GET_PROC(EnumerateInstanceVersion);
-    LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&mInstanceVersion));
-    LOG_ALWAYS_FATAL_IF(mInstanceVersion < VK_MAKE_VERSION(1, 1, 0));
+    uint32_t instanceVersion;
+    LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion));
+    LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0));
 
     GrVkExtensions extensions;
     LOG_ALWAYS_FATAL_IF(!this->setupDevice(extensions, mPhysicalDeviceFeatures2));
@@ -398,7 +398,7 @@
     backendContext.fDevice = mDevice;
     backendContext.fQueue = mGraphicsQueue;
     backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex;
-    backendContext.fInstanceVersion = mInstanceVersion;
+    backendContext.fMaxAPIVersion = mAPIVersion;
     backendContext.fVkExtensions = &extensions;
     backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
     backendContext.fGetProc = std::move(getProc);
@@ -446,7 +446,7 @@
             .device = mDevice,
             .queue = mGraphicsQueue,
             .graphics_queue_index = mGraphicsQueueIndex,
-            .instance_version = mInstanceVersion,
+            .api_version = mAPIVersion,
             .enabled_instance_extension_names = mInstanceExtensions.data(),
             .enabled_instance_extension_names_length =
                     static_cast<uint32_t>(mInstanceExtensions.size()),
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index abe78ef..6426fe2 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -246,7 +246,7 @@
     VkCommandBuffer mDummyCB = VK_NULL_HANDLE;
 
     // Variables saved to populate VkFunctorInitParams.
-    uint32_t mInstanceVersion = 0u;
+    static const uint32_t mAPIVersion = VK_MAKE_VERSION(1, 1, 0);
     std::vector<const char*> mInstanceExtensions;
     std::vector<const char*> mDeviceExtensions;
     VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures2{};
diff --git a/media/Android.bp b/media/Android.bp
index 3181a29..e7d5faf 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -66,7 +66,9 @@
 filegroup {
     name: "media1-srcs",
     srcs: [
+        "apex/java/android/media/MediaDescription.java",
         "apex/java/android/media/MediaParceledListSlice.java",
+        "apex/java/android/media/Rating.java",
         "apex/java/android/media/VolumeProvider.java",
         "apex/java/android/media/browse/MediaBrowser.java",
         "apex/java/android/media/browse/MediaBrowserUtils.java",
diff --git a/media/java/android/media/MediaDescription.aidl b/media/apex/java/android/media/MediaDescription.aidl
similarity index 100%
rename from media/java/android/media/MediaDescription.aidl
rename to media/apex/java/android/media/MediaDescription.aidl
diff --git a/media/java/android/media/MediaDescription.java b/media/apex/java/android/media/MediaDescription.java
similarity index 93%
rename from media/java/android/media/MediaDescription.java
rename to media/apex/java/android/media/MediaDescription.java
index 31079e5..39eeb3e 100644
--- a/media/java/android/media/MediaDescription.java
+++ b/media/apex/java/android/media/MediaDescription.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package android.media;
 
 import android.annotation.Nullable;
@@ -226,7 +242,7 @@
             return false;
         }
 
-        if (!(o instanceof MediaDescription)){
+        if (!(o instanceof MediaDescription)) {
             return false;
         }
 
@@ -375,6 +391,11 @@
             return this;
         }
 
+        /**
+         * Build {@link MediaDescription}.
+         *
+         * @return a new media description.
+         */
         public MediaDescription build() {
             return new MediaDescription(mMediaId, mTitle, mSubtitle, mDescription, mIcon, mIconUri,
                     mExtras, mMediaUri);
diff --git a/media/java/android/media/Rating.aidl b/media/apex/java/android/media/Rating.aidl
similarity index 100%
rename from media/java/android/media/Rating.aidl
rename to media/apex/java/android/media/Rating.aidl
diff --git a/media/java/android/media/Rating.java b/media/apex/java/android/media/Rating.java
similarity index 93%
rename from media/java/android/media/Rating.java
rename to media/apex/java/android/media/Rating.java
index 04d5364f..ffe7e48 100644
--- a/media/java/android/media/Rating.java
+++ b/media/apex/java/android/media/Rating.java
@@ -33,7 +33,7 @@
  * through one of the factory methods.
  */
 public final class Rating implements Parcelable {
-    private final static String TAG = "Rating";
+    private static final String TAG = "Rating";
 
     /**
      * @hide
@@ -55,40 +55,40 @@
      * type, but can be used by other classes to indicate they do not support
      * Rating.
      */
-    public final static int RATING_NONE = 0;
+    public static final int RATING_NONE = 0;
 
     /**
      * A rating style with a single degree of rating, "heart" vs "no heart". Can be used to
      * indicate the content referred to is a favorite (or not).
      */
-    public final static int RATING_HEART = 1;
+    public static final int RATING_HEART = 1;
 
     /**
      * A rating style for "thumb up" vs "thumb down".
      */
-    public final static int RATING_THUMB_UP_DOWN = 2;
+    public static final int RATING_THUMB_UP_DOWN = 2;
 
     /**
      * A rating style with 0 to 3 stars.
      */
-    public final static int RATING_3_STARS = 3;
+    public static final int RATING_3_STARS = 3;
 
     /**
      * A rating style with 0 to 4 stars.
      */
-    public final static int RATING_4_STARS = 4;
+    public static final int RATING_4_STARS = 4;
 
     /**
      * A rating style with 0 to 5 stars.
      */
-    public final static int RATING_5_STARS = 5;
+    public static final int RATING_5_STARS = 5;
 
     /**
      * A rating style expressed as a percentage.
      */
-    public final static int RATING_PERCENTAGE = 6;
+    public static final int RATING_PERCENTAGE = 6;
 
-    private final static float RATING_NOT_RATED = -1.0f;
+    private static final float RATING_NOT_RATED = -1.0f;
 
     private final int mRatingStyle;
 
@@ -116,8 +116,7 @@
         dest.writeFloat(mRatingValue);
     }
 
-    public static final Parcelable.Creator<Rating> CREATOR
-            = new Parcelable.Creator<Rating>() {
+    public static final Parcelable.Creator<Rating> CREATOR = new Parcelable.Creator<Rating>() {
         /**
          * Rebuilds a Rating previously stored with writeToParcel().
          * @param p    Parcel object to read the Rating from
@@ -205,7 +204,7 @@
                 break;
             default:
                 Log.e(TAG, "Invalid rating style (" + starRatingStyle + ") for a star rating");
-                        return null;
+                return null;
         }
         if ((starRating < 0.0f) || (starRating > maxRating)) {
             Log.e(TAG, "Trying to set out of range star-based rating");
@@ -281,16 +280,16 @@
      *    not star-based, or if it is unrated.
      */
     public float getStarRating() {
+        float ratingValue = -1.0f;
         switch (mRatingStyle) {
             case RATING_3_STARS:
             case RATING_4_STARS:
             case RATING_5_STARS:
                 if (isRated()) {
-                    return mRatingValue;
+                    ratingValue = mRatingValue;
                 }
-            default:
-                return -1.0f;
         }
+        return ratingValue;
     }
 
     /**
diff --git a/native/webview/plat_support/draw_fn.h b/native/webview/plat_support/draw_fn.h
index e31ce19..5b3e496 100644
--- a/native/webview/plat_support/draw_fn.h
+++ b/native/webview/plat_support/draw_fn.h
@@ -84,7 +84,7 @@
   VkDevice device;
   VkQueue queue;
   uint32_t graphics_queue_index;
-  uint32_t instance_version;
+  uint32_t api_version;
   const char* const* enabled_instance_extension_names;
   uint32_t enabled_instance_extension_names_length;
   const char* const* enabled_device_extension_names;
diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp
index afe103a..6deb47f 100644
--- a/native/webview/plat_support/draw_functor.cpp
+++ b/native/webview/plat_support/draw_functor.cpp
@@ -102,7 +102,7 @@
       .device = init_vk_params.device,
       .queue = init_vk_params.queue,
       .graphics_queue_index = init_vk_params.graphics_queue_index,
-      .instance_version = init_vk_params.instance_version,
+      .api_version = init_vk_params.api_version,
       .enabled_instance_extension_names =
           init_vk_params.enabled_instance_extension_names,
       .enabled_instance_extension_names_length =
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 7eaf04b..0a571c5 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -60,7 +60,6 @@
 
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import java.io.IOException;
@@ -107,11 +106,11 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
         logMetricsEvent(MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY);
 
         mCm = ConnectivityManager.from(this);
         mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
-        mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
         mUserAgent =
                 getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
         mUrl = getUrl();
@@ -637,7 +636,7 @@
     }
 
     private void logMetricsEvent(int event) {
-        MetricsLogger.action(this, event, getPackageName());
+        mCaptivePortal.logEvent(event, getPackageName());
     }
 
     private static final SparseArray<String> SSL_ERRORS = new SparseArray<>();
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index 010a810..7fb51b9 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -22,6 +22,7 @@
     coreApp="true">
 
     <uses-permission android:name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" />
+    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
 
     <application android:label="@string/app_name"
         android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index f21561f..b34efc4 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -687,6 +687,15 @@
                                     }
                                     sendMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED, response);
                                 }
+
+                                @Override
+                                public void logEvent(int eventId, String packageName)
+                                        throws RemoteException {
+                                    mContext.enforceCallingPermission(
+                                            android.Manifest.permission.CONNECTIVITY_INTERNAL,
+                                            "CaptivePortal");
+                                    mCallback.logCaptivePortalLoginEvent(eventId, packageName);
+                                }
                             }));
                     final CaptivePortalProbeResult probeRes = mLastPortalProbeResult;
                     intent.putExtra(EXTRA_CAPTIVE_PORTAL_URL, probeRes.detectUrl);
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f523481..ec70f8c 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -618,8 +618,6 @@
     <string name="wifi_display_certification">Wireless display certification</string>
     <!-- Setting Checkbox title whether to enable WiFi Verbose Logging. [CHAR LIMIT=40] -->
     <string name="wifi_verbose_logging">Enable Wi\u2011Fi Verbose Logging</string>
-    <!-- Setting Checkbox title whether to enable connected MAC randomization -->
-    <string name="wifi_connected_mac_randomization">Connected MAC Randomization</string>
     <!-- Setting Checkbox title whether to always keep mobile data active. [CHAR LIMIT=80] -->
     <string name="mobile_data_always_on">Mobile data always active</string>
     <!-- Setting Checkbox title whether to enable hardware acceleration for tethering. [CHAR LIMIT=80] -->
@@ -675,8 +673,6 @@
     <string name="wifi_display_certification_summary">Show options for wireless display certification</string>
     <!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] -->
     <string name="wifi_verbose_logging_summary">Increase Wi\u2011Fi logging level, show per SSID RSSI in Wi\u2011Fi Picker</string>
-    <!-- Setting Checkbox title whether to enable connected MAC randomization -->
-    <string name="wifi_connected_mac_randomization_summary">Randomize MAC address when connecting to Wi\u2011Fi networks</string>
     <!-- Label indicating network has been manually marked as metered -->
     <string name="wifi_metered_label">Metered</string>
     <!-- Label indicating network has been manually marked as unmetered -->
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 3877c90..6ca8261 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1511,9 +1511,6 @@
                 Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED,
                 GlobalSettingsProto.Wifi.VERBOSE_LOGGING_ENABLED);
         dumpSetting(s, p,
-                Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED,
-                GlobalSettingsProto.Wifi.CONNECTED_MAC_RANDOMIZATION_ENABLED);
-        dumpSetting(s, p,
                 Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
                 GlobalSettingsProto.Wifi.MAX_DHCP_RETRY_COUNT);
         dumpSetting(s, p,
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3453e79..a18eb76 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -593,11 +593,6 @@
                 android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
                 android:process=":ui"
                 android:visibleToInstantApps="true">
-            <intent-filter>
-                <action android:name="android.intent.action.CHOOSER_UI" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE" />
-            </intent-filter>
         </activity>
 
         <!-- Doze with notifications, run in main sysui process for every user  -->
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index f66a57b..9b3d7ed 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -137,8 +137,10 @@
     }
 
     public NotificationIconAreaController createNotificationIconAreaController(Context context,
-            StatusBar statusBar, StatusBarStateController statusBarStateController) {
-        return new NotificationIconAreaController(context, statusBar, statusBarStateController);
+            StatusBar statusBar, StatusBarStateController statusBarStateController,
+            NotificationListener listener) {
+        return new NotificationIconAreaController(context, statusBar, statusBarStateController,
+                listener);
     }
 
     public KeyguardIndicationController createKeyguardIndicationController(Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 83fd970..8731bd5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -238,14 +238,14 @@
      */
     public void setExpandedBubble(BubbleView bubbleToExpand) {
         mExpandedBubble = bubbleToExpand;
-        boolean prevExpanded = mIsExpanded;
-        mIsExpanded = true;
-        if (!prevExpanded) {
+        if (!mIsExpanded) {
             // If we weren't previously expanded we should animate open.
             animateExpansion(true /* expand */);
         } else {
-            // If we were expanded just update the views
+            // Otherwise just update the views
+            // TODO: probably animate / page to expanded one
             updateExpandedBubble();
+            updatePointerPosition();
             requestUpdate();
         }
         mExpandedBubble.getEntry().setShowInShadeWhenBubble(false);
@@ -387,7 +387,6 @@
             mIsExpanded = shouldExpand;
             updateExpandedBubble();
             applyCurrentState();
-            //requestUpdate();
 
             mIsAnimating = true;
 
@@ -400,7 +399,10 @@
             if (shouldExpand) {
                 mBubbleContainer.setController(mExpandedAnimationController);
                 mExpandedAnimationController.expandFromStack(
-                                mStackAnimationController.getStackPosition(), updateAfter);
+                                mStackAnimationController.getStackPosition(), () -> {
+                                updatePointerPosition();
+                                updateAfter.run();
+                        });
             } else {
                 mBubbleContainer.cancelAllAnimations();
                 mExpandedAnimationController.collapseBackToStack(
@@ -649,10 +651,7 @@
             }
             // Bubble with notification as expanded state doesn't need a header / title
             mExpandedViewContainer.setHeaderText(null);
-
         }
-        float pointerPosition = mExpandedBubble.getPosition().x + (mExpandedBubble.getWidth() / 2);
-        mExpandedViewContainer.setPointerPosition((int) pointerPosition);
     }
 
     private void applyCurrentState() {
@@ -690,6 +689,14 @@
         }
     }
 
+    private void updatePointerPosition() {
+        if (mExpandedBubble != null) {
+            float pointerPosition = mExpandedBubble.getPosition().x
+                    + (mExpandedBubble.getWidth() / 2f);
+            mExpandedViewContainer.setPointerPosition((int) pointerPosition);
+        }
+    }
+
     private void applyRowState(ExpandableNotificationRow view) {
         view.reset();
         view.setHeadsUp(false);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
index 968bd28..60dceef 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
@@ -165,6 +165,11 @@
         }
     }
 
+    @Override
+    public void clearAccessibilityFocus() {
+        // We should not be here.
+    }
+
     public static AccessibilityNodeInfo obtainRootAccessibilityNodeInfo() {
         AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
         info.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID,
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
index db5c244..e2688f1 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.content.DialogInterface
 import android.content.Intent
+import android.content.pm.PackageManager
 import android.content.res.ColorStateList
 import android.os.UserHandle
 import android.util.IconDrawableFactory
@@ -157,16 +158,21 @@
         } else {
             icons.visibility = View.GONE
         }
-        item.setOnClickListener(object : View.OnClickListener {
-            val intent = Intent(Intent.ACTION_REVIEW_APP_PERMISSION_USAGE)
-                    .putExtra(Intent.EXTRA_PACKAGE_NAME, app.packageName)
-                    .putExtra(Intent.EXTRA_USER, UserHandle.getUserHandleForUid(app.uid))
-            override fun onClick(v: View?) {
-                Dependency.get(ActivityStarter::class.java)
-                        .postStartActivityDismissingKeyguard(intent, 0)
-                dismissDialog?.invoke()
-            }
-        })
+        try {
+            // Check if package exists
+            context.packageManager.getPackageInfo(app.packageName, 0)
+            item.setOnClickListener(object : View.OnClickListener {
+                val intent = Intent(Intent.ACTION_REVIEW_APP_PERMISSION_USAGE)
+                        .putExtra(Intent.EXTRA_PACKAGE_NAME, app.packageName)
+                        .putExtra(Intent.EXTRA_USER, UserHandle.getUserHandleForUid(app.uid))
+                override fun onClick(v: View?) {
+                    Dependency.get(ActivityStarter::class.java)
+                            .postStartActivityDismissingKeyguard(intent, 0)
+                    dismissDialog?.invoke()
+                }
+            })
+        } catch (e: PackageManager.NameNotFoundException) {}
+
         itemList.addView(item)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index f3a46ce..0583843 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -20,6 +20,8 @@
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
 import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_CHILD_NOTIFICATIONS;
 
+import android.annotation.SuppressLint;
+import android.app.NotificationManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.RemoteException;
@@ -32,10 +34,13 @@
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins;
 
+import java.util.ArrayList;
+
 /**
  * This class handles listening to notification updates and passing them along to
  * NotificationPresenter to be displayed to the user.
  */
+@SuppressLint("OverrideAbstract")
 public class NotificationListener extends NotificationListenerWithPlugins {
     private static final String TAG = "NotificationListener";
 
@@ -47,6 +52,7 @@
     private final NotificationGroupManager mGroupManager =
             Dependency.get(NotificationGroupManager.class);
 
+    private final ArrayList<NotificationSettingsListener> mSettingsListeners = new ArrayList<>();
     private final Context mContext;
 
     protected NotificationPresenter mPresenter;
@@ -55,6 +61,10 @@
         mContext = context;
     }
 
+    public void addNotificationSettingsListener(NotificationSettingsListener listener) {
+        mSettingsListeners.add(listener);
+    }
+
     @Override
     public void onListenerConnected() {
         if (DEBUG) Log.d(TAG, "onListenerConnected");
@@ -70,6 +80,8 @@
                 mEntryManager.addNotification(sbn, currentRanking);
             }
         });
+        NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
+        onStatusBarIconsBehaviorChanged(noMan.shouldHideSilentStatusBarIcons());
     }
 
     @Override
@@ -133,6 +145,13 @@
         }
     }
 
+    @Override
+    public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+        for (NotificationSettingsListener listener : mSettingsListeners) {
+            listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
+        }
+    }
+
     public void setUpWithPresenter(NotificationPresenter presenter) {
         mPresenter = presenter;
 
@@ -144,4 +163,10 @@
             Log.e(TAG, "Unable to register notification listener", e);
         }
     }
+
+    public interface NotificationSettingsListener {
+
+        default void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { }
+
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index e86996a..9e99fe9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -11,9 +11,7 @@
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
-import androidx.annotation.NonNull;
-import androidx.collection.ArrayMap;
-
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.ContrastColorUtil;
 import com.android.internal.widget.ViewClippingUtil;
@@ -21,6 +19,7 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.StatusBarStateController;
@@ -28,11 +27,13 @@
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.tuner.TunerService;
 
 import java.util.ArrayList;
 import java.util.function.Function;
 
+import androidx.annotation.NonNull;
+import androidx.collection.ArrayMap;
+
 /**
  * A controller for the space in the status bar to the left of the system icons. This area is
  * normally reserved for notifications.
@@ -46,18 +47,19 @@
     private final NotificationEntryManager mEntryManager;
     private final Runnable mUpdateStatusBarIcons = this::updateStatusBarIcons;
     private final StatusBarStateController mStatusBarStateController;
-    private final TunerService.Tunable mTunable = new TunerService.Tunable() {
-        @Override
-        public void onTuningChanged(String key, String newValue) {
-            if (key.equals(LOW_PRIORITY)) {
-                mShowLowPriority = "1".equals(newValue)
-                        || !NotificationUtils.useNewInterruptionModel(mContext);
-                if (mNotificationScrollLayout != null) {
-                    updateStatusBarIcons();
+    @VisibleForTesting
+    final NotificationListener.NotificationSettingsListener mSettingsListener =
+            new NotificationListener.NotificationSettingsListener() {
+                @Override
+                public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+                    if (NotificationUtils.useNewInterruptionModel(mContext)) {
+                        mShowLowPriority = !hideSilentStatusIcons;
+                        if (mNotificationScrollLayout != null) {
+                            updateStatusBarIcons();
+                        }
+                    }
                 }
-            }
-        }
-    };
+            };
 
     private int mIconSize;
     private int mIconHPadding;
@@ -71,7 +73,7 @@
     private ViewGroup mNotificationScrollLayout;
     private Context mContext;
     private boolean mFullyDark;
-    private boolean mShowLowPriority;
+    private boolean mShowLowPriority = true;
 
     /**
      * Ratio representing being awake or in ambient mode, where 1 is dark and 0 awake.
@@ -90,15 +92,15 @@
             view -> view instanceof StatusBarWindowView;
 
     public NotificationIconAreaController(Context context, StatusBar statusBar,
-            StatusBarStateController statusBarStateController) {
+            StatusBarStateController statusBarStateController,
+            NotificationListener notificationListener) {
         mStatusBar = statusBar;
         mContrastColorUtil = ContrastColorUtil.getInstance(context);
         mContext = context;
         mEntryManager = Dependency.get(NotificationEntryManager.class);
         mStatusBarStateController = statusBarStateController;
         mStatusBarStateController.addCallback(this);
-
-        Dependency.get(TunerService.class).addTunable(mTunable, LOW_PRIORITY);
+        notificationListener.addNotificationSettingsListener(mSettingsListener);
 
         initializeNotificationAreaViews(context);
     }
@@ -243,6 +245,11 @@
                 true /* hideRepliedMessages */);
     }
 
+    @VisibleForTesting
+    boolean shouldShouldLowPriorityIcons() {
+        return mShowLowPriority;
+    }
+
     /**
      * Updates the notification icons for a host layout. This will ensure that the notification
      * host layout will have the same icons like the ones in here.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 1470d0f..ceadd1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -801,7 +801,8 @@
         mNotificationLogger.setUpWithContainer(notifListContainer);
 
         mNotificationIconAreaController = SystemUIFactory.getInstance()
-                .createNotificationIconAreaController(context, this, mStatusBarStateController);
+                .createNotificationIconAreaController(
+                        context, this, mStatusBarStateController, mNotificationListener);
         inflateShelf();
         mNotificationIconAreaController.setupShelf(mNotificationShelf);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
index c880172..bcf5964 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java
@@ -17,10 +17,12 @@
 package com.android.systemui.statusbar;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
@@ -55,6 +57,7 @@
     // Dependency mocks:
     @Mock private NotificationEntryManager mEntryManager;
     @Mock private NotificationRemoteInputManager mRemoteInputManager;
+    @Mock private NotificationManager mNotificationManager;
 
     private NotificationListener mListener;
     private StatusBarNotification mSbn;
@@ -67,6 +70,7 @@
                 mRemoteInputManager);
         mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
                 new Handler(TestableLooper.get(this).getLooper()));
+        mContext.addMockSystemService(NotificationManager.class, mNotificationManager);
 
         when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
 
@@ -106,4 +110,28 @@
         // RankingMap may be modified by plugins.
         verify(mEntryManager).updateNotificationRanking(any());
     }
+
+    @Test
+    public void testOnConnectReadStatusBarSetting() {
+        NotificationListener.NotificationSettingsListener settingsListener =
+                mock(NotificationListener.NotificationSettingsListener.class);
+        mListener.addNotificationSettingsListener(settingsListener);
+
+        when(mNotificationManager.shouldHideSilentStatusBarIcons()).thenReturn(true);
+
+        mListener.onListenerConnected();
+
+        verify(settingsListener).onStatusBarIconsBehaviorChanged(true);
+    }
+
+    @Test
+    public void testOnStatusBarIconsBehaviorChanged() {
+        NotificationListener.NotificationSettingsListener settingsListener =
+                mock(NotificationListener.NotificationSettingsListener.class);
+        mListener.addNotificationSettingsListener(settingsListener);
+
+        mListener.onStatusBarIconsBehaviorChanged(true);
+
+        verify(settingsListener).onStatusBarIconsBehaviorChanged(true);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
new file mode 100644
index 0000000..13145b8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 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.statusbar.phone;
+
+import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.LightBarTransitionsController.DarkIntensityApplier;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotificationIconAreaControllerTest extends SysuiTestCase {
+
+    @Mock
+    private NotificationListener mListener;
+    @Mock
+    StatusBar mStatusBar;
+    @Mock
+    StatusBarStateController mStatusBarStateController;
+    private NotificationIconAreaController mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        mController = new NotificationIconAreaController(mContext, mStatusBar,
+                mStatusBarStateController, mListener);
+    }
+
+    @Test
+    public void testNotificationIcons_featureOff() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(), NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
+        assertTrue(mController.shouldShouldLowPriorityIcons());
+    }
+
+    @Test
+    public void testNotificationIcons_featureOn_settingHideIcons() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(), NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
+        mController.mSettingsListener.onStatusBarIconsBehaviorChanged(true);
+
+        assertFalse(mController.shouldShouldLowPriorityIcons());
+    }
+
+    @Test
+    public void testNotificationIcons_featureOn_settingShowIcons() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(), NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
+        mController.mSettingsListener.onStatusBarIconsBehaviorChanged(false);
+
+        assertTrue(mController.shouldShouldLowPriorityIcons());
+    }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index f88d521..47cd917 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3024,9 +3024,19 @@
         }
 
         public void clearAccessibilityFocusNotLocked(int windowId) {
-            AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(windowId);
-            if (focus != null) {
-                focus.performAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+            RemoteAccessibilityConnection connection;
+            synchronized (mLock) {
+                connection = getConnectionLocked(windowId);
+                if (connection == null) {
+                    return;
+                }
+            }
+            try {
+                connection.getRemote().clearAccessibilityFocus();
+            } catch (RemoteException re) {
+                if (DEBUG) {
+                    Slog.e(LOG_TAG, "Error calling clearAccessibilityFocus()");
+                }
             }
         }
 
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 7d228f1..8b2c1b9 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -1863,7 +1863,7 @@
             // The agent was running with a stub Application object, so shut it down.
             // !!! We hardcode the confirmation UI's package name here rather than use a
             //     manifest flag!  TODO something less direct.
-            if (app.uid >= Process.FIRST_APPLICATION_UID
+            if (!UserHandle.isCore(app.uid)
                     && !app.packageName.equals("com.android.backupconfirm")) {
                 if (MORE_DEBUG) Slog.d(TAG, "Killing agent host process");
                 mActivityManager.killApplicationProcess(app.processName, app.uid);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 7763d7b..324c2d9 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -45,9 +45,9 @@
 import android.os.Bundle;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.EventLog;
 import android.util.Slog;
 
@@ -1174,7 +1174,7 @@
                 //     b. the app does not state android:killAfterRestore="false" in its manifest
                 final int appFlags = mCurrentPackage.applicationInfo.flags;
                 final boolean killAfterRestore =
-                        (mCurrentPackage.applicationInfo.uid >= Process.FIRST_APPLICATION_UID)
+                        !UserHandle.isCore(mCurrentPackage.applicationInfo.uid)
                                 && ((mRestoreDescription.getDataType()
                                 == RestoreDescription.TYPE_FULL_STREAM)
                                 || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0));
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index 2db8928..7ee3047 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -31,7 +31,6 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.content.pm.SigningInfo;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Slog;
@@ -72,7 +71,7 @@
         }
 
         // 2. they run as a system-level uid
-        if ((app.uid < Process.FIRST_APPLICATION_UID)) {
+        if (UserHandle.isCore(app.uid)) {
             // and the backup is happening for non-system user
             if (userId != UserHandle.USER_SYSTEM && !app.packageName.equals(
                     PACKAGE_MANAGER_SENTINEL)) {
diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
index cce5b3b..97bde9c 100644
--- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
@@ -34,7 +34,7 @@
 import android.content.pm.Signature;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.Process;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -162,7 +162,7 @@
                             if (AppBackupUtils.signaturesMatch(sigs, pkg, pmi)) {
                                 // If this is a system-uid app without a declared backup agent,
                                 // don't restore any of the file data.
-                                if ((pkg.applicationInfo.uid < Process.FIRST_APPLICATION_UID)
+                                if (UserHandle.isCore(pkg.applicationInfo.uid)
                                         && (pkg.applicationInfo.backupAgentName == null)) {
                                     Slog.w(TAG, "Installed app " + info.packageName
                                             + " has restricted uid and no agent");
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index f4b235a..f3b8098 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -53,7 +53,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.os.Bundle;
-import android.os.Process;
+import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.server.backup.FileMetadata;
@@ -404,8 +404,7 @@
             if ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0) {
                 // Restore system-uid-space packages only if they have
                 // defined a custom backup agent
-                if ((pkgInfo.applicationInfo.uid
-                        >= Process.FIRST_APPLICATION_UID)
+                if (!UserHandle.isCore(pkgInfo.applicationInfo.uid)
                         || (pkgInfo.applicationInfo.backupAgentName != null)) {
                     // Verify signatures against any installed version; if they
                     // don't match, then we fall though and ignore the data.  The
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index de7c8cc..58263fc 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -146,6 +146,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnInfo;
@@ -2685,6 +2686,11 @@
                     EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE,
                     mNai.network.netId));
         }
+
+        @Override
+        public void logCaptivePortalLoginEvent(int eventId, String packageName) {
+            new MetricsLogger().action(eventId, packageName);
+        }
     }
 
     private boolean networkRequiresValidation(NetworkAgentInfo nai) {
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 84577f1..4507193 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.pm.VersionedPackage;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
@@ -230,7 +231,6 @@
         return null;
     }
 
-    // TODO(zezeozue:) Accept current versionCodes of failing packages?
     /**
      * Called when a process fails either due to a crash or ANR.
      *
@@ -239,15 +239,16 @@
      *
      * <p>This method could be called frequently if there is a severe problem on the device.
      */
-    public void onPackageFailure(String[] packages) {
+    public void onPackageFailure(List<VersionedPackage> packages) {
         mWorkerHandler.post(() -> {
             synchronized (mLock) {
                 if (mAllObservers.isEmpty()) {
                     return;
                 }
 
-                for (int pIndex = 0; pIndex < packages.length; pIndex++) {
-                    String packageToReport = packages[pIndex];
+                for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
+                    String packageToReport = packages.get(pIndex).getPackageName();
+                    long packageVersionCode = packages.get(pIndex).getVersionCode();
                     // Observer that will receive failure for packageToReport
                     PackageHealthObserver currentObserverToNotify = null;
                     int currentObserverImpact = Integer.MAX_VALUE;
@@ -258,7 +259,8 @@
                         PackageHealthObserver registeredObserver = observer.mRegisteredObserver;
                         if (registeredObserver != null
                                 && observer.onPackageFailure(packageToReport)) {
-                            int impact = registeredObserver.onHealthCheckFailed(packageToReport);
+                            int impact = registeredObserver.onHealthCheckFailed(packageToReport,
+                                    packageVersionCode);
                             if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE
                                     && impact < currentObserverImpact) {
                                 currentObserverToNotify = registeredObserver;
@@ -269,7 +271,7 @@
 
                     // Execute action with least user impact
                     if (currentObserverToNotify != null) {
-                        currentObserverToNotify.execute(packageToReport);
+                        currentObserverToNotify.execute(packageToReport, packageVersionCode);
                     }
                 }
             }
@@ -313,14 +315,14 @@
          * @return any one of {@link PackageHealthObserverImpact} to express the impact
          * to the user on {@link #execute}
          */
-        @PackageHealthObserverImpact int onHealthCheckFailed(String packageName);
+        @PackageHealthObserverImpact int onHealthCheckFailed(String packageName, long versionCdoe);
 
         /**
          * Executes mitigation for {@link #onHealthCheckFailed}.
          *
          * @return {@code true} if action was executed successfully, {@code false} otherwise
          */
-        boolean execute(String packageName);
+        boolean execute(String packageName, long versionCode);
 
         // TODO(zezeozue): Ensure uniqueness?
         /**
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index a634b57..f153ab9 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -34,6 +34,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.VersionedPackage;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Message;
@@ -60,6 +61,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Collections;
+import java.util.List;
 
 /**
  * Controls error conditions in applications.
@@ -411,7 +413,7 @@
             } else {
                 // If a non-persistent app is stuck in crash loop, we want to inform
                 // the package watchdog, maybe an update or experiment can be rolled back.
-                mPackageWatchdog.onPackageFailure(r.getPackageList());
+                mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode());
             }
         }
 
@@ -830,7 +832,7 @@
 
     void handleShowAnrUi(Message msg) {
         Dialog dialogToShow = null;
-        String[] packageList = null;
+        List<VersionedPackage> packageList = null;
         synchronized (mService) {
             AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
             final ProcessRecord proc = data.proc;
@@ -839,7 +841,7 @@
                 return;
             }
             if (!proc.isPersistent()) {
-                packageList = proc.getPackageList();
+                packageList = proc.getPackageListWithVersionCode();
             }
             if (proc.anrDialog != null) {
                 Slog.e(TAG, "App already has anr dialog: " + proc);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 580d688..7ae77d5 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -32,6 +32,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.VersionedPackage;
 import android.content.res.CompatibilityInfo;
 import android.os.Binder;
 import android.os.Debug;
@@ -66,6 +67,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 /**
  * Full information about a particular process that
@@ -974,6 +976,18 @@
         return list;
     }
 
+    public List<VersionedPackage> getPackageListWithVersionCode() {
+        int size = pkgList.size();
+        if (size == 0) {
+            return null;
+        }
+        List<VersionedPackage> list = new ArrayList<>();
+        for (int i = 0; i < pkgList.size(); i++) {
+            list.add(new VersionedPackage(pkgList.keyAt(i), pkgList.valueAt(i).appVersion));
+        }
+        return list;
+    }
+
     WindowProcessController getWindowProcessController() {
         return mWindowProcessController;
     }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b89768a..c9df86e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1241,27 +1241,59 @@
         }
     }
 
+    @Nullable
+    private IBinder getDisplayToken(int displayId) {
+        synchronized (mSyncRoot) {
+            final LogicalDisplay display = mLogicalDisplays.get(displayId);
+            if (display != null) {
+                final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
+                if (device != null) {
+                    return device.getDisplayTokenLocked();
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private boolean screenshotInternal(int displayId, Surface outSurface) {
+        final IBinder token = getDisplayToken(displayId);
+        if (token == null) {
+            return false;
+        }
+        SurfaceControl.screenshot(token, outSurface);
+        return true;
+    }
+
     @VisibleForTesting
     DisplayedContentSamplingAttributes getDisplayedContentSamplingAttributesInternal(
             int displayId) {
-        IBinder displayToken = SurfaceControl.getBuiltInDisplay(displayId);
-        return SurfaceControl.getDisplayedContentSamplingAttributes(displayToken);
+        final IBinder token = getDisplayToken(displayId);
+        if (token == null) {
+            return null;
+        }
+        return SurfaceControl.getDisplayedContentSamplingAttributes(token);
     }
 
     @VisibleForTesting
     boolean setDisplayedContentSamplingEnabledInternal(
             int displayId, boolean enable, int componentMask, int maxFrames) {
-        IBinder displayToken = SurfaceControl.getBuiltInDisplay(displayId);
+        final IBinder token = getDisplayToken(displayId);
+        if (token == null) {
+            return false;
+        }
         return SurfaceControl.setDisplayedContentSamplingEnabled(
-                displayToken, enable, componentMask, maxFrames);
+                token, enable, componentMask, maxFrames);
     }
 
     @VisibleForTesting
     DisplayedContentSample getDisplayedContentSampleInternal(int displayId,
             long maxFrames, long timestamp) {
-        IBinder displayToken = SurfaceControl.getBuiltInDisplay(displayId);
-        return SurfaceControl.getDisplayedContentSample(
-            displayToken, maxFrames, timestamp);
+        final IBinder token = getDisplayToken(displayId);
+        if (token == null) {
+            return null;
+        }
+        return SurfaceControl.getDisplayedContentSample(token, maxFrames, timestamp);
     }
 
     private void clearViewportsLocked() {
@@ -2257,20 +2289,7 @@
 
         @Override
         public boolean screenshot(int displayId, Surface outSurface) {
-            synchronized (mSyncRoot) {
-                final LogicalDisplay display = mLogicalDisplays.get(displayId);
-                if (display != null) {
-                    final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
-                    if (device != null) {
-                        final IBinder token = device.getDisplayTokenLocked();
-                        if (token != null) {
-                            SurfaceControl.screenshot(token, outSurface);
-                            return true;
-                        }
-                    }
-                }
-            }
-            return false;
+            return screenshotInternal(displayId, outSurface);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 669ff2b..5e7ea05 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -234,6 +234,7 @@
     private static native void nativeReloadPointerIcons(long ptr);
     private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
     private static native void nativeSetPointerCapture(long ptr, boolean detached);
+    private static native boolean nativeCanDispatchToDisplay(long ptr, int deviceId, int displayId);
 
     // Input event injection constants defined in InputDispatcher.h.
     private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
@@ -1890,6 +1891,16 @@
         return new String[0];
     }
 
+    /**
+     * Gets if an input device could dispatch to the given display".
+     * @param deviceId The input device id.
+     * @param displayId The specific display id.
+     * @return True if the device could dispatch to the given display, false otherwise.
+     */
+    public boolean canDispatchToDisplay(int deviceId, int displayId) {
+        return nativeCanDispatchToDisplay(mPtr, deviceId, displayId);
+    }
+
     // Native callback.
     private int getKeyRepeatTimeout() {
         return ViewConfiguration.getKeyRepeatTimeout();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 467b192..ba187c0 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -198,6 +198,7 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
@@ -2366,6 +2367,28 @@
         }
 
         @Override
+        public boolean shouldHideSilentStatusIcons(String callingPkg) {
+            checkCallerIsSameApp(callingPkg);
+
+            if (isCallerSystemOrPhone()
+                    || mListeners.isListenerPackage(callingPkg)) {
+                return mPreferencesHelper.shouldHideSilentStatusIcons();
+            } else {
+                throw new SecurityException("Only available for notification listeners");
+            }
+        }
+
+        @Override
+        public void setHideSilentStatusIcons(boolean hide) {
+            checkCallerIsSystem();
+
+            mPreferencesHelper.setHideSilentStatusIcons(hide);
+            handleSavePolicyFile();
+
+            mListeners.onStatusBarIconsBehaviorChanged(hide);
+        }
+
+        @Override
         public int getPackageImportance(String pkg) {
             checkCallerIsSystemOrSameApp(pkg);
             return mPreferencesHelper.getImportance(pkg, Binder.getCallingUid());
@@ -3633,6 +3656,22 @@
         }
 
         @Override
+        public ComponentName getAllowedNotificationAssistantForUser(int userId) {
+            checkCallerIsSystem();
+            List<ComponentName> allowedComponents = mAssistants.getAllowedComponents(userId);
+            if (allowedComponents.size() > 1) {
+                throw new IllegalStateException(
+                        "At most one NotificationAssistant: " + allowedComponents.size());
+            }
+            return CollectionUtils.firstOrNull(allowedComponents);
+        }
+
+        @Override
+        public ComponentName getAllowedNotificationAssistant() {
+            return getAllowedNotificationAssistantForUser(getCallingUserHandle().getIdentifier());
+        }
+
+        @Override
         public boolean isNotificationListenerAccessGranted(ComponentName listener) {
             Preconditions.checkNotNull(listener);
             checkCallerIsSystemOrSameApp(listener.getPackageName());
@@ -3700,8 +3739,15 @@
         @Override
         public void setNotificationAssistantAccessGrantedForUser(ComponentName assistant,
                 int userId, boolean granted) throws RemoteException {
-            Preconditions.checkNotNull(assistant);
             checkCallerIsSystemOrShell();
+            if (assistant == null) {
+                ComponentName allowedAssistant = CollectionUtils.firstOrNull(
+                        mAssistants.getAllowedComponents(userId));
+                if (allowedAssistant != null) {
+                    setNotificationAssistantAccessGrantedForUser(allowedAssistant, userId, false);
+                }
+                return;
+            }
             final long identity = Binder.clearCallingIdentity();
             try {
                 if (mAllowedManagedServicePackages.test(assistant.getPackageName())) {
@@ -7242,6 +7288,26 @@
                 }
             }
         }
+
+        @Override
+        protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId,
+                boolean isPrimary, boolean enabled) {
+            // Ensures that only one component is enabled at a time
+            if (enabled) {
+                List<ComponentName> allowedComponents = getAllowedComponents(userId);
+                if (!allowedComponents.isEmpty()) {
+                    ComponentName currentComponent = CollectionUtils.firstOrNull(allowedComponents);
+                    if (currentComponent.flattenToString().equals(pkgOrComponent)) return;
+                    try {
+                        getBinderService().setNotificationAssistantAccessGrantedForUser(
+                                currentComponent, userId, false);
+                    } catch (RemoteException e) {
+                        e.rethrowFromSystemServer();
+                    }
+                }
+            }
+            super.setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled);
+        }
     }
 
     public class NotificationListeners extends ManagedServices {
@@ -7324,6 +7390,20 @@
             return mLightTrimListeners.contains(info) ? TRIM_LIGHT : TRIM_FULL;
         }
 
+        public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) {
+            for (final ManagedServiceInfo info : getServices()) {
+                mHandler.post(() -> {
+                    final INotificationListener listener = (INotificationListener) info.service;
+                     try {
+                        listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
+                    } catch (RemoteException ex) {
+                        Log.e(TAG, "unable to notify listener "
+                                + "(hideSilentStatusIcons): " + listener, ex);
+                    }
+                });
+            }
+        }
+
         /**
          * asynchronously notify all listeners about a new notification
          *
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 3f0043c..6ed4f5c 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -76,6 +76,7 @@
     private static final String TAG_CHANNEL = "channel";
     private static final String TAG_GROUP = "channelGroup";
     private static final String TAG_DELEGATE = "delegate";
+    private static final String TAG_STATUS_ICONS = "status_icons";
 
     private static final String ATT_VERSION = "version";
     private static final String ATT_NAME = "name";
@@ -89,10 +90,13 @@
     private static final String ATT_APP_USER_LOCKED_FIELDS = "app_user_locked_fields";
     private static final String ATT_ENABLED = "enabled";
     private static final String ATT_USER_ALLOWED = "allowed";
+    private static final String ATT_HIDE_SILENT = "hide_silent";
 
     private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT;
     private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
     private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED;
+    @VisibleForTesting
+    static final boolean DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS = false;
     private static final boolean DEFAULT_SHOW_BADGE = true;
     private static final boolean DEFAULT_ALLOW_BUBBLE = true;
     private static final boolean DEFAULT_OEM_LOCKED_IMPORTANCE  = false;
@@ -124,6 +128,7 @@
 
     private SparseBooleanArray mBadgingEnabled;
     private boolean mAreChannelsBypassingDnd;
+    private boolean mHideSilentStatusBarIcons;
 
     public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
             ZenModeHelper zenHelper) {
@@ -143,9 +148,8 @@
         String tag = parser.getName();
         if (!TAG_RANKING.equals(tag)) return;
         synchronized (mPackagePreferences) {
-            // Clobber groups and channels with the xml, but don't delete other data that wasn't present
-
-            // at the time of serialization.
+            // Clobber groups and channels with the xml, but don't delete other data that wasn't
+            // present at the time of serialization.
             mRestoredWithoutUids.clear();
             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
                 tag = parser.getName();
@@ -153,7 +157,10 @@
                     return;
                 }
                 if (type == XmlPullParser.START_TAG) {
-                    if (TAG_PACKAGE.equals(tag)) {
+                    if (TAG_STATUS_ICONS.equals(tag)) {
+                        mHideSilentStatusBarIcons = XmlUtils.readBooleanAttribute(
+                                parser, ATT_HIDE_SILENT, DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS);
+                    } else if (TAG_PACKAGE.equals(tag)) {
                         int uid = XmlUtils.readIntAttribute(parser, ATT_UID, UNKNOWN_UID);
                         String name = parser.getAttributeValue(null, ATT_NAME);
                         if (!TextUtils.isEmpty(name)) {
@@ -375,6 +382,11 @@
     public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
         out.startTag(null, TAG_RANKING);
         out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION));
+        if (mHideSilentStatusBarIcons != DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS) {
+            out.startTag(null, TAG_STATUS_ICONS);
+            out.attribute(null, ATT_HIDE_SILENT, String.valueOf(mHideSilentStatusBarIcons));
+            out.endTag(null, TAG_STATUS_ICONS);
+        }
 
         synchronized (mPackagePreferences) {
             final int N = mPackagePreferences.size();
@@ -781,6 +793,14 @@
         }
     }
 
+    public boolean shouldHideSilentStatusIcons() {
+        return mHideSilentStatusBarIcons;
+    }
+
+    public void setHideSilentStatusIcons(boolean hide) {
+        mHideSilentStatusBarIcons = hide;
+    }
+
     public void lockChannelsForOEM(String[] appOrChannelList) {
         if (appOrChannelList == null) {
             return;
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 6f1eeeb..dc18dfc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -61,6 +61,10 @@
 import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
+import android.content.rollback.IRollbackManager;
+import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.RollbackInfo;
+import android.content.rollback.RollbackManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
@@ -263,6 +267,8 @@
                     return getStagedSessions();
                 case "uninstall-system-updates":
                     return uninstallSystemUpdates();
+                case "rollback-app":
+                    return runRollbackApp();
                 default: {
                     String nextArg = getNextArg();
                     if (nextArg == null) {
@@ -348,6 +354,55 @@
         return 1;
     }
 
+    private int runRollbackApp() {
+        final PrintWriter pw = getOutPrintWriter();
+
+        final String packageName = getNextArgRequired();
+        if (packageName == null) {
+            pw.println("Error: package name not specified");
+            return 1;
+        }
+
+        final LocalIntentReceiver receiver = new LocalIntentReceiver();
+        try {
+            IRollbackManager rm = IRollbackManager.Stub.asInterface(
+                    ServiceManager.getService(Context.ROLLBACK_SERVICE));
+
+            RollbackInfo rollback = null;
+            for (RollbackInfo r : (List<RollbackInfo>) rm.getAvailableRollbacks().getList()) {
+                for (PackageRollbackInfo info : r.getPackages()) {
+                    if (packageName.equals(info.getPackageName())) {
+                        rollback = r;
+                        break;
+                    }
+                }
+            }
+
+            if (rollback == null) {
+                pw.println("No available rollbacks for: " + packageName);
+                return 1;
+            }
+
+            rm.commitRollback(rollback.getRollbackId(),
+                    ParceledListSlice.<VersionedPackage>emptyList(),
+                    "com.android.shell", receiver.getIntentSender());
+        } catch (RemoteException re) {
+            // Cannot happen.
+        }
+
+        final Intent result = receiver.getResult();
+        final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
+                RollbackManager.STATUS_FAILURE);
+        if (status == RollbackManager.STATUS_SUCCESS) {
+            pw.println("Success");
+            return 0;
+        } else {
+            pw.println("Failure ["
+                    + result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE) + "]");
+            return 1;
+        }
+    }
+
     private void setParamsSize(InstallParams params, String inPath) {
         if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
             final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");
diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
new file mode 100644
index 0000000..8dd0760
--- /dev/null
+++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2019 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.rollback;
+
+import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.PackageRollbackInfo.RestoreInfo;
+import android.content.rollback.RollbackInfo;
+import android.os.storage.StorageManager;
+import android.util.IntArray;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.Installer;
+import com.android.server.pm.Installer.InstallerException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Encapsulates the logic for initiating userdata snapshots and rollbacks via installd.
+ */
+@VisibleForTesting
+// TODO(narayan): Reason about the failure scenarios that involve one or more IPCs to installd
+// failing. We need to decide what course of action to take if calls to snapshotAppData or
+// restoreAppDataSnapshot fail.
+public class AppDataRollbackHelper {
+    private static final String TAG = "RollbackManager";
+
+    private final Installer mInstaller;
+
+    public AppDataRollbackHelper(Installer installer) {
+        mInstaller = installer;
+    }
+
+    /**
+     * Creates an app data snapshot for a specified {@code packageName} for {@code installedUsers},
+     * a specified set of users for whom the package is installed.
+     *
+     * @return a list of users for which the snapshot is pending, usually because data for one or
+     *         more users is still credential locked.
+     */
+    public IntArray snapshotAppData(String packageName, int[] installedUsers) {
+        final IntArray pendingBackups = new IntArray();
+        for (int user : installedUsers) {
+            final int storageFlags;
+            if (isUserCredentialLocked(user)) {
+                // We've encountered a user that hasn't unlocked on a FBE device, so we can't copy
+                // across app user data until the user unlocks their device.
+                Log.v(TAG, "User: " + user + " isn't unlocked, skipping CE userdata backup.");
+                storageFlags = Installer.FLAG_STORAGE_DE;
+                pendingBackups.add(user);
+            } else {
+                storageFlags = Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE;
+            }
+
+            try {
+                mInstaller.snapshotAppData(packageName, user, storageFlags);
+            } catch (InstallerException ie) {
+                Log.e(TAG, "Unable to create app data snapshot for: " + packageName
+                        + ", userId: " + user, ie);
+            }
+        }
+
+        return pendingBackups;
+    }
+
+    /**
+     * Restores an app data snapshot for a specified package ({@code packageName},
+     * {@code rollbackData}) for a specified {@code userId}.
+     *
+     * @return {@code true} iff. a change to the {@code rollbackData} has been made. Changes to
+     *         {@code rollbackData} are restricted to the removal or addition of {@code userId} to
+     *         the list of pending backups or restores.
+     */
+    public boolean restoreAppData(String packageName, RollbackData rollbackData,
+            int userId, int appId, long ceDataInode, String seInfo) {
+        if (rollbackData == null) {
+            return false;
+        }
+
+        if (!rollbackData.inProgress) {
+            Log.e(TAG, "Request to restore userData for: " + packageName
+                    + ", but no rollback in progress.");
+            return false;
+        }
+
+        PackageRollbackInfo packageInfo = RollbackManagerServiceImpl.getPackageRollbackInfo(
+                rollbackData, packageName);
+        int storageFlags = Installer.FLAG_STORAGE_DE;
+
+        final IntArray pendingBackups = packageInfo.getPendingBackups();
+        final List<RestoreInfo> pendingRestores = packageInfo.getPendingRestores();
+        boolean changedRollbackData = false;
+
+        // If we still have a userdata backup pending for this user, it implies that the user
+        // hasn't unlocked their device between the point of backup and the point of restore,
+        // so the data cannot have changed. We simply skip restoring CE data in this case.
+        if (pendingBackups != null && pendingBackups.indexOf(userId) != -1) {
+            pendingBackups.remove(pendingBackups.indexOf(userId));
+            changedRollbackData = true;
+        } else {
+            // There's no pending CE backup for this user, which means that we successfully
+            // managed to backup data for the user, which means we seek to restore it
+            if (isUserCredentialLocked(userId)) {
+                // We've encountered a user that hasn't unlocked on a FBE device, so we can't
+                // copy across app user data until the user unlocks their device.
+                pendingRestores.add(new RestoreInfo(userId, appId, seInfo));
+                changedRollbackData = true;
+            } else {
+                // This user has unlocked, we can proceed to restore both CE and DE data.
+                storageFlags = storageFlags | Installer.FLAG_STORAGE_CE;
+            }
+        }
+
+        try {
+            mInstaller.restoreAppDataSnapshot(packageName, appId, ceDataInode,
+                    seInfo, userId, storageFlags);
+        } catch (InstallerException ie) {
+            Log.e(TAG, "Unable to restore app data snapshot: " + packageName, ie);
+        }
+
+        return changedRollbackData;
+    }
+
+    /**
+     * Computes the list of pending backups and restores for {@code userId} given lists of
+     * available and recent rollbacks. Packages pending backup for the given user are added
+     * to {@code pendingBackups} and packages pending restore are added to {@code pendingRestores}
+     * along with their corresponding {@code RestoreInfo}.
+     *
+     * @return the list of {@code RollbackData} that have been modified during this computation.
+     */
+    public List<RollbackData> computePendingBackupsAndRestores(int userId,
+            ArrayList<String> pendingBackupPackages, Map<String, RestoreInfo> pendingRestores,
+            List<RollbackData> availableRollbacks, List<RollbackInfo> recentRollbacks) {
+        List<RollbackData> rd = new ArrayList<>();
+        // First check with the list of available rollbacks to see whether there are any
+        // pending backup operations that we've not managed to execute.
+        for (RollbackData data : availableRollbacks) {
+            for (PackageRollbackInfo info : data.packages) {
+                final IntArray pendingBackupUsers = info.getPendingBackups();
+                if (pendingBackupUsers != null) {
+                    final int idx = pendingBackupUsers.indexOf(userId);
+                    if (idx != -1) {
+                        pendingBackupPackages.add(info.getPackageName());
+                        pendingBackupUsers.remove(idx);
+                        if (rd.indexOf(data) == -1) {
+                            rd.add(data);
+                        }
+                    }
+                }
+            }
+        }
+
+        // Then check with the list of recently executed rollbacks to see whether there are
+        // any rollback operations
+        for (RollbackInfo data : recentRollbacks) {
+            for (PackageRollbackInfo info : data.getPackages()) {
+                final RestoreInfo ri = info.getRestoreInfo(userId);
+                if (ri != null) {
+                    if (pendingBackupPackages.contains(info.getPackageName())) {
+                        // This implies that the user hasn't unlocked their device between
+                        // the request to backup data for this user and the request to restore
+                        // it, so we do nothing here.
+                        pendingBackupPackages.remove(info.getPackageName());
+                    } else {
+                        pendingRestores.put(info.getPackageName(), ri);
+                    }
+
+                    info.removeRestoreInfo(ri);
+                }
+            }
+        }
+
+        return rd;
+    }
+
+    /**
+     * Commits the list of pending backups and restores for a given {@code userId}.
+     */
+    public void commitPendingBackupAndRestoreForUser(int userId,
+            ArrayList<String> pendingBackups, Map<String, RestoreInfo> pendingRestores) {
+        if (!pendingBackups.isEmpty()) {
+            for (String packageName : pendingBackups) {
+                try {
+                    mInstaller.snapshotAppData(packageName, userId, Installer.FLAG_STORAGE_CE);
+                } catch (InstallerException ie) {
+                    Log.e(TAG, "Unable to create app data snapshot for: " + packageName, ie);
+                }
+            }
+        }
+
+        // TODO(narayan): Should we perform the restore before the backup for packages that have
+        // both backups and restores pending ? We could get into this case if we have a pending
+        // restore from a rollback + a snapshot request from a new restore.
+        if (!pendingRestores.isEmpty()) {
+            for (String packageName : pendingRestores.keySet()) {
+                try {
+                    final RestoreInfo ri = pendingRestores.get(packageName);
+
+                    // TODO(narayan): Verify that the user of "0" for ceDataInode is accurate
+                    // here. We know that the user has unlocked (and that their CE data is
+                    // available) so we shouldn't need to resort to the fallback path.
+                    mInstaller.restoreAppDataSnapshot(packageName, ri.appId,
+                            0 /* ceDataInode */, ri.seInfo, userId, Installer.FLAG_STORAGE_CE);
+                } catch (InstallerException ie) {
+                    Log.e(TAG, "Unable to restore app data snapshot for: " + packageName, ie);
+                }
+            }
+        }
+    }
+
+    /**
+     * @return {@code true} iff. {@code userId} is locked on an FBE device.
+     */
+    @VisibleForTesting
+    public boolean isUserCredentialLocked(int userId) {
+        return StorageManager.isFileEncryptedNativeOrEmulated()
+                && !StorageManager.isUserKeyUnlocked(userId);
+    }
+}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerService.java b/services/core/java/com/android/server/rollback/RollbackManagerService.java
index 4b5e764..ba6cddd 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerService.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerService.java
@@ -39,4 +39,9 @@
         mService = new RollbackManagerServiceImpl(getContext());
         publishBinderService(Context.ROLLBACK_SERVICE, mService);
     }
+
+    @Override
+    public void onUnlockUser(int user) {
+        mService.onUnlockUser(user);
+    }
 }
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 289618e..5eb137b 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -31,6 +31,7 @@
 import android.content.pm.VersionedPackage;
 import android.content.rollback.IRollbackManager;
 import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.PackageRollbackInfo.RestoreInfo;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
 import android.os.Binder;
@@ -39,14 +40,13 @@
 import android.os.HandlerThread;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
-import android.os.storage.StorageManager;
+import android.util.IntArray;
 import android.util.Log;
 import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.LocalServices;
 import com.android.server.pm.Installer;
-import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.PackageManagerServiceUtils;
 
 import java.io.File;
@@ -111,6 +111,7 @@
     private final HandlerThread mHandlerThread;
     private final Installer mInstaller;
     private final RollbackPackageHealthObserver mPackageHealthObserver;
+    private final AppDataRollbackHelper mUserdataHelper;
 
     RollbackManagerServiceImpl(Context context) {
         mContext = context;
@@ -124,6 +125,7 @@
         mRollbackStore = new RollbackStore(new File(Environment.getDataDirectory(), "rollback"));
 
         mPackageHealthObserver = new RollbackPackageHealthObserver(mContext);
+        mUserdataHelper = new AppDataRollbackHelper(mInstaller);
 
         // Kick off loading of the rollback data from strorage in a background
         // thread.
@@ -424,6 +426,35 @@
         }
     }
 
+    void onUnlockUser(int userId) {
+        getHandler().post(() -> {
+            final ArrayList<String> pendingBackupPackages = new ArrayList<>();
+            final Map<String, RestoreInfo> pendingRestorePackages = new HashMap<>();
+            final List<RollbackData> changed;
+            synchronized (mLock) {
+                ensureRollbackDataLoadedLocked();
+                changed = mUserdataHelper.computePendingBackupsAndRestores(userId,
+                        pendingBackupPackages, pendingRestorePackages, mAvailableRollbacks,
+                        mRecentlyExecutedRollbacks);
+            }
+
+            mUserdataHelper.commitPendingBackupAndRestoreForUser(userId,
+                    pendingBackupPackages, pendingRestorePackages);
+
+            for (RollbackData rd : changed) {
+                try {
+                    mRollbackStore.saveAvailableRollback(rd);
+                } catch (IOException ioe) {
+                    Log.e(TAG, "Unable to save rollback info for : " + rd.rollbackId, ioe);
+                }
+            }
+
+            synchronized (mLock) {
+                mRollbackStore.saveRecentlyExecutedRollbacks(mRecentlyExecutedRollbacks);
+            }
+        });
+    }
+
     /**
      * Load rollback data from storage if it has not already been loaded.
      * After calling this funciton, mAvailableRollbacks and
@@ -533,6 +564,20 @@
         // that are necessary to keep track of.
         synchronized (mLock) {
             ensureRollbackDataLoadedLocked();
+
+            // This should never happen because we can't have any pending backups left after
+            // a rollback has been executed. See AppDataRollbackHelper#restoreAppData where we
+            // clear all pending backups at the point of restore because they're guaranteed to be
+            // no-ops.
+            //
+            // We may, however, have one or more pending restores left to handle.
+            for (PackageRollbackInfo target : rollback.getPackages()) {
+                if (target.getPendingBackups().size() > 0) {
+                    Log.e(TAG, "No backups allowed to be pending for: " + target);
+                    target.getPendingBackups().clear();
+                }
+            }
+
             mRecentlyExecutedRollbacks.add(rollback);
             mRollbackStore.saveRecentlyExecutedRollbacks(mRecentlyExecutedRollbacks);
         }
@@ -701,27 +746,12 @@
         VersionedPackage installedVersion = new VersionedPackage(packageName,
                 installedPackage.getLongVersionCode());
 
-        for (int user : installedUsers) {
-            final int storageFlags;
-            if (StorageManager.isFileEncryptedNativeOrEmulated()
-                    && !StorageManager.isUserKeyUnlocked(user)) {
-                // We've encountered a user that hasn't unlocked on a FBE device, so we can't copy
-                // across app user data until the user unlocks their device.
-                Log.e(TAG, "User: " + user + " isn't unlocked, skipping CE userdata backup.");
-                storageFlags = Installer.FLAG_STORAGE_DE;
-            } else {
-                storageFlags = Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE;
-            }
 
-            try {
-                mInstaller.snapshotAppData(packageName, user, storageFlags);
-            } catch (InstallerException ie) {
-                Log.e(TAG, "Unable to create app data snapshot for: " + packageName, ie);
-            }
-        }
+        final IntArray pendingBackups = mUserdataHelper.snapshotAppData(packageName,
+                installedUsers);
 
-        PackageRollbackInfo info = new PackageRollbackInfo(newVersion, installedVersion);
-
+        PackageRollbackInfo info = new PackageRollbackInfo(newVersion, installedVersion,
+                pendingBackups, new ArrayList<>());
         RollbackData data;
         try {
             synchronized (mLock) {
@@ -760,40 +790,24 @@
         }
 
         getHandler().post(() -> {
-            PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
             final RollbackData rollbackData = getRollbackForPackage(packageName);
-            if (rollbackData == null) {
-                pmi.finishPackageInstall(token, false);
-                return;
-            }
-
-            if (!rollbackData.inProgress) {
-                Log.e(TAG, "Request to restore userData for: " + packageName
-                        + ", but no rollback in progress.");
-                pmi.finishPackageInstall(token, false);
-                return;
-            }
-
-            final int storageFlags;
-            if (StorageManager.isFileEncryptedNativeOrEmulated()
-                    && !StorageManager.isUserKeyUnlocked(userId)) {
-                // We've encountered a user that hasn't unlocked on a FBE device, so we can't copy
-                // across app user data until the user unlocks their device.
-                Log.e(TAG, "User: " + userId + " isn't unlocked, skipping CE userdata restore.");
-
-                storageFlags = Installer.FLAG_STORAGE_DE;
-            } else {
-                storageFlags = Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE;
-            }
-
-            try {
-                mInstaller.restoreAppDataSnapshot(packageName, appId, ceDataInode,
-                        seInfo, userId, storageFlags);
-            } catch (InstallerException ie) {
-                Log.e(TAG, "Unable to restore app data snapshot: " + packageName, ie);
-            }
-
+            final boolean changedRollbackData = mUserdataHelper.restoreAppData(packageName,
+                    rollbackData, userId, appId, ceDataInode, seInfo);
+            final PackageManagerInternal pmi = LocalServices.getService(
+                    PackageManagerInternal.class);
             pmi.finishPackageInstall(token, false);
+
+            // We've updated metadata about this rollback, so save it to flash.
+            if (changedRollbackData) {
+                try {
+                    mRollbackStore.saveAvailableRollback(rollbackData);
+                } catch (IOException ioe) {
+                    // TODO(narayan): What is the right thing to do here ? This isn't a fatal error,
+                    // since it will only result in us trying to restore data again, which will be
+                    // a no-op if there's no data available.
+                    Log.e(TAG, "Unable to save available rollback: " + packageName, ioe);
+                }
+            }
         });
     }
 
@@ -900,10 +914,8 @@
             ensureRollbackDataLoadedLocked();
             for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
                 RollbackData data = mAvailableRollbacks.get(i);
-                for (PackageRollbackInfo info : data.packages) {
-                    if (info.getPackageName().equals(packageName)) {
-                        return data;
-                    }
+                if (getPackageRollbackInfo(data, packageName) != null) {
+                    return data;
                 }
             }
         }
@@ -926,6 +938,22 @@
                 }
             }
         }
+
+        return null;
+    }
+
+    /**
+     * Returns the {@code PackageRollbackInfo} associated with {@code packageName} from
+     * a specified {@code RollbackData}.
+     */
+    static PackageRollbackInfo getPackageRollbackInfo(RollbackData data,
+            String packageName) {
+        for (PackageRollbackInfo info : data.packages) {
+            if (info.getPackageName().equals(packageName)) {
+                return info;
+            }
+        }
+
         return null;
     }
 
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 2880103..b3cc6de 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInstaller;
+import android.content.pm.VersionedPackage;
 import android.content.rollback.PackageRollbackInfo;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
@@ -41,12 +42,10 @@
     private static final String TAG = "RollbackPackageHealthObserver";
     private static final String NAME = "rollback-observer";
     private Context mContext;
-    private RollbackManager mRollbackManager;
     private Handler mHandler;
 
     RollbackPackageHealthObserver(Context context) {
         mContext = context;
-        mRollbackManager = mContext.getSystemService(RollbackManager.class);
         HandlerThread handlerThread = new HandlerThread("RollbackPackageHealthObserver");
         handlerThread.start();
         mHandler = handlerThread.getThreadHandler();
@@ -54,8 +53,10 @@
     }
 
     @Override
-    public int onHealthCheckFailed(String packageName) {
-        RollbackInfo rollback = getAvailableRollback(packageName);
+    public int onHealthCheckFailed(String packageName, long versionCode) {
+        RollbackInfo rollback =
+                getAvailableRollback(mContext.getSystemService(RollbackManager.class),
+                    packageName, versionCode);
         if (rollback == null) {
             // Don't handle the notification, no rollbacks available for the package
             return PackageHealthObserverImpact.USER_IMPACT_NONE;
@@ -65,8 +66,9 @@
     }
 
     @Override
-    public boolean execute(String packageName) {
-        RollbackInfo rollback = getAvailableRollback(packageName);
+    public boolean execute(String packageName, long versionCode) {
+        RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
+        RollbackInfo rollback = getAvailableRollback(rollbackManager, packageName, versionCode);
         if (rollback == null) {
             // Expected a rollback to be available, what happened?
             return false;
@@ -86,12 +88,9 @@
         });
 
         // TODO(zezeozue): Log initiated metrics
-        // TODO: Pass the package as a cause package instead of using
-        // Collections.emptyList once the version of the failing package is
-        // easily available.
         mHandler.post(() ->
-                mRollbackManager.commitRollback(rollback.getRollbackId(),
-                    Collections.emptyList(),
+                rollbackManager.commitRollback(rollback.getRollbackId(),
+                    Collections.singletonList(new VersionedPackage(packageName, versionCode)),
                     rollbackReceiver.getIntentSender()));
         // Assume rollback executed successfully
         return true;
@@ -110,11 +109,13 @@
         PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs);
     }
 
-    private RollbackInfo getAvailableRollback(String packageName) {
-        for (RollbackInfo rollback : mRollbackManager.getAvailableRollbacks()) {
+    private RollbackInfo getAvailableRollback(RollbackManager rollbackManager,
+            String packageName, long versionCode) {
+        for (RollbackInfo rollback : rollbackManager.getAvailableRollbacks()) {
             for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
-                if (packageName.equals(packageRollback.getPackageName())) {
-                    // TODO(zezeozue): Only rollback if rollback version == failed package version
+                if (packageName.equals(packageRollback.getPackageName())
+                        && packageRollback.getVersionRolledBackFrom().getVersionCode()
+                        == versionCode) {
                     return rollback;
                 }
             }
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 98ebb09..c70f47d 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -16,9 +16,12 @@
 
 package com.android.server.rollback;
 
+import android.annotation.NonNull;
 import android.content.pm.VersionedPackage;
 import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.PackageRollbackInfo.RestoreInfo;
 import android.content.rollback.RollbackInfo;
+import android.util.IntArray;
 import android.util.Log;
 
 import libcore.io.IoUtils;
@@ -99,6 +102,64 @@
     }
 
     /**
+     * Converts an {@code JSONArray} of integers to an {@code IntArray}.
+     */
+    private static @NonNull IntArray convertToIntArray(@NonNull JSONArray jsonArray)
+            throws JSONException {
+        if (jsonArray.length() == 0) {
+            return new IntArray();
+        }
+
+        final int[] ret = new int[jsonArray.length()];
+        for (int i = 0; i < ret.length; ++i) {
+            ret[i] = jsonArray.getInt(i);
+        }
+
+        return IntArray.wrap(ret);
+    }
+
+    /**
+     * Converts an {@code IntArray} into an {@code JSONArray} of integers.
+     */
+    private static @NonNull JSONArray convertToJsonArray(@NonNull IntArray intArray) {
+        JSONArray jsonArray = new JSONArray();
+        for (int i = 0; i < intArray.size(); ++i) {
+            jsonArray.put(intArray.get(i));
+        }
+
+        return jsonArray;
+    }
+
+    private static @NonNull JSONArray convertToJsonArray(@NonNull List<RestoreInfo> list)
+            throws JSONException {
+        JSONArray jsonArray = new JSONArray();
+        for (RestoreInfo ri : list) {
+            JSONObject jo = new JSONObject();
+            jo.put("userId", ri.userId);
+            jo.put("appId", ri.appId);
+            jo.put("seInfo", ri.seInfo);
+            jsonArray.put(jo);
+        }
+
+        return jsonArray;
+    }
+
+    private static @NonNull ArrayList<RestoreInfo> convertToRestoreInfoArray(
+            @NonNull JSONArray array) throws JSONException {
+        ArrayList<RestoreInfo> restoreInfos = new ArrayList<>();
+
+        for (int i = 0; i < array.length(); ++i) {
+            JSONObject jo = array.getJSONObject(i);
+            restoreInfos.add(new RestoreInfo(
+                    jo.getInt("userId"),
+                    jo.getInt("appId"),
+                    jo.getString("seInfo")));
+        }
+
+        return restoreInfos;
+    }
+
+    /**
      * Reads the list of recently executed rollbacks from persistent storage.
      */
     List<RollbackInfo> loadRecentlyExecutedRollbacks() {
@@ -239,6 +300,12 @@
         JSONObject json = new JSONObject();
         json.put("versionRolledBackFrom", toJson(info.getVersionRolledBackFrom()));
         json.put("versionRolledBackTo", toJson(info.getVersionRolledBackTo()));
+
+        IntArray pendingBackups = info.getPendingBackups();
+        List<RestoreInfo> pendingRestores = info.getPendingRestores();
+        json.put("pendingBackups", convertToJsonArray(pendingBackups));
+        json.put("pendingRestores", convertToJsonArray(pendingRestores));
+
         return json;
     }
 
@@ -247,7 +314,14 @@
                 json.getJSONObject("versionRolledBackFrom"));
         VersionedPackage versionRolledBackTo = versionedPackageFromJson(
                 json.getJSONObject("versionRolledBackTo"));
-        return new PackageRollbackInfo(versionRolledBackFrom, versionRolledBackTo);
+
+        final IntArray pendingBackups = convertToIntArray(
+                json.getJSONArray("pendingBackups"));
+        final ArrayList<RestoreInfo> pendingRestores = convertToRestoreInfoArray(
+                json.getJSONArray("pendingRestores"));
+
+        return new PackageRollbackInfo(versionRolledBackFrom, versionRolledBackTo,
+                pendingBackups, pendingRestores);
     }
 
     private JSONArray versionedPackagesToJson(List<VersionedPackage> packages)
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 3426ba6..080f965 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -29,6 +29,7 @@
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.FLAG_PRIVATE;
+import static android.view.Display.INVALID_DISPLAY;
 import static android.view.InsetsState.TYPE_IME;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_180;
@@ -43,6 +44,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
 import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
@@ -140,9 +142,11 @@
 import android.graphics.Region;
 import android.graphics.Region.Op;
 import android.hardware.display.DisplayManagerInternal;
+import android.os.Binder;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -157,6 +161,7 @@
 import android.view.Gravity;
 import android.view.InputChannel;
 import android.view.InputDevice;
+import android.view.InputWindowHandle;
 import android.view.InsetsState.InternalInsetType;
 import android.view.MagnificationSpec;
 import android.view.RemoteAnimationDefinition;
@@ -515,6 +520,9 @@
 
     private final InsetsStateController mInsetsStateController;
 
+    private SurfaceControl mParentSurfaceControl;
+    private InputWindowHandle mPortalWindowHandle;
+
     // Last systemUiVisibility we received from status bar.
     private int mLastStatusBarVisibility = 0;
     // Last systemUiVisibility we dispatched to windows.
@@ -1657,35 +1665,42 @@
         final int len = devices != null ? devices.length : 0;
         for (int i = 0; i < len; i++) {
             InputDevice device = devices[i];
-            if (!device.isVirtual()) {
-                final int sources = device.getSources();
-                final int presenceFlag = device.isExternal() ?
-                        WindowManagerPolicy.PRESENCE_EXTERNAL :
-                        WindowManagerPolicy.PRESENCE_INTERNAL;
+            // Ignore virtual input device.
+            if (device.isVirtual()) {
+                continue;
+            }
 
-                // TODO(multi-display): Configure on per-display basis.
-                if (mWmService.mIsTouchDevice) {
-                    if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
-                            InputDevice.SOURCE_TOUCHSCREEN) {
-                        config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
-                    }
-                } else {
-                    config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
-                }
+            // Check if input device can dispatch events to current display.
+            // If display type is virtual, will follow the default display.
+            if (!mWmService.mInputManager.canDispatchToDisplay(device.getId(),
+                    displayInfo.type == Display.TYPE_VIRTUAL ? DEFAULT_DISPLAY : mDisplayId)) {
+                continue;
+            }
 
-                if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
-                    config.navigation = Configuration.NAVIGATION_TRACKBALL;
-                    navigationPresence |= presenceFlag;
-                } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
-                        && config.navigation == Configuration.NAVIGATION_NONAV) {
-                    config.navigation = Configuration.NAVIGATION_DPAD;
-                    navigationPresence |= presenceFlag;
-                }
+            final int sources = device.getSources();
+            final int presenceFlag = device.isExternal()
+                    ? WindowManagerPolicy.PRESENCE_EXTERNAL : WindowManagerPolicy.PRESENCE_INTERNAL;
 
-                if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
-                    config.keyboard = Configuration.KEYBOARD_QWERTY;
-                    keyboardPresence |= presenceFlag;
+            if (mWmService.mIsTouchDevice) {
+                if ((sources & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) {
+                    config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
                 }
+            } else {
+                config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+            }
+
+            if ((sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
+                config.navigation = Configuration.NAVIGATION_TRACKBALL;
+                navigationPresence |= presenceFlag;
+            } else if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD
+                    && config.navigation == Configuration.NAVIGATION_NONAV) {
+                config.navigation = Configuration.NAVIGATION_DPAD;
+                navigationPresence |= presenceFlag;
+            }
+
+            if (device.getKeyboardType() == InputDevice.KEYBOARD_TYPE_ALPHABETIC) {
+                config.keyboard = Configuration.KEYBOARD_QWERTY;
+                keyboardPresence |= presenceFlag;
             }
         }
 
@@ -2410,10 +2425,7 @@
             win.getTouchableRegion(mTmpRegion);
             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
         }
-        for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
-            final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
-            win.amendTapExcludeRegion(mTouchExcludeRegion);
-        }
+        amendWindowTapExcludeRegion(mTouchExcludeRegion);
         // TODO(multi-display): Support docked stacks on secondary displays.
         if (mDisplayId == DEFAULT_DISPLAY && getSplitScreenPrimaryStack() != null) {
             mDividerControllerLocked.getTouchRegion(mTmpRect);
@@ -2425,6 +2437,18 @@
         }
     }
 
+    /**
+     * Union the region with all the tap exclude region provided by windows on this display.
+     *
+     * @param inOutRegion The region to be amended.
+     */
+    void amendWindowTapExcludeRegion(Region inOutRegion) {
+        for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
+            final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
+            win.amendTapExcludeRegion(inOutRegion);
+        }
+    }
+
     @Override
     void switchUser() {
         super.switchUser();
@@ -3586,6 +3610,13 @@
     private void updateBounds() {
         calculateBounds(mDisplayInfo, mTmpBounds);
         setBounds(mTmpBounds);
+        if (mPortalWindowHandle != null && mParentSurfaceControl != null) {
+            mPortalWindowHandle.touchableRegion.getBounds(mTmpRect);
+            if (!mTmpBounds.equals(mTmpRect)) {
+                mPortalWindowHandle.touchableRegion.set(mTmpBounds);
+                mPendingTransaction.setInputWindowInfo(mParentSurfaceControl, mPortalWindowHandle);
+            }
+        }
     }
 
     // Determines the current display bounds based on the current state
@@ -4830,15 +4861,43 @@
                 || mWmService.mForceDesktopModeOnExternalDisplays;
     }
 
-     /**
+    /**
      * Re-parent the DisplayContent's top surfaces, {@link #mWindowingLayer} and
      * {@link #mOverlayLayer} to the specified surfaceControl.
      *
-     * @param surfaceControlHandle The new SurfaceControl, where the DisplayContent's
-     *                             surfaces will be re-parented to.
+     * @param sc The new SurfaceControl, where the DisplayContent's surfaces will be re-parented to.
      */
     void reparentDisplayContent(SurfaceControl sc) {
-        mPendingTransaction.reparent(mWindowingLayer, sc)
-                .reparent(mOverlayLayer, sc);
+        mParentSurfaceControl = sc;
+        if (mPortalWindowHandle == null) {
+            mPortalWindowHandle = createPortalWindowHandle(sc.toString());
+        }
+        mPendingTransaction.setInputWindowInfo(sc, mPortalWindowHandle)
+                .reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc);
+    }
+
+    /**
+     * Create a portal window handle for input. This window transports any touch to the display
+     * indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window.
+     *
+     * @param name The name of the portal window handle.
+     * @return the new portal window handle.
+     */
+    private InputWindowHandle createPortalWindowHandle(String name) {
+        // Let surface flinger to set the display ID of this input window handle because we don't
+        // know which display the parent surface control is on.
+        final InputWindowHandle portalWindowHandle = new InputWindowHandle(
+                null /* inputApplicationHandle */, null /* clientWindow */, INVALID_DISPLAY);
+        portalWindowHandle.name = name;
+        portalWindowHandle.token = new Binder();
+        portalWindowHandle.layoutParamsFlags =
+                FLAG_SPLIT_TOUCH | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL;
+        getBounds(mTmpBounds);
+        portalWindowHandle.touchableRegion.set(mTmpBounds);
+        portalWindowHandle.scaleFactor = 1f;
+        portalWindowHandle.ownerPid = Process.myPid();
+        portalWindowHandle.ownerUid = Process.myUid();
+        portalWindowHandle.portalToDisplayId = mDisplayId;
+        return portalWindowHandle;
     }
 }
diff --git a/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java b/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
index cbc936f..0a4ab67 100644
--- a/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
+++ b/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
@@ -49,7 +49,9 @@
     void amendRegion(Region region, Rect boundingRegion) {
         for (int i = mTapExcludeRects.size() - 1; i>= 0 ; --i) {
             final Rect rect = mTapExcludeRects.valueAt(i);
-            rect.intersect(boundingRegion);
+            if (boundingRegion != null) {
+                rect.intersect(boundingRegion);
+            }
             region.union(rect);
         }
     }
diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
index 2e5df45..dd94af6 100644
--- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
@@ -70,6 +70,18 @@
                     // method target window will lose the focus.
                     return;
                 }
+                final Region windowTapExcludeRegion = Region.obtain();
+                mDisplayContent.amendWindowTapExcludeRegion(windowTapExcludeRegion);
+                if (windowTapExcludeRegion.contains(x, y)) {
+                    windowTapExcludeRegion.recycle();
+                    // The user is tapping on the window tap exclude region. We don't move this
+                    // display to top. A window tap exclude region, for example, may be set by an
+                    // ActivityView, and the region would match the bounds of both the ActivityView
+                    // and the virtual display in it. In this case, we would take the tap that is on
+                    // the embedded virtual display instead of this display.
+                    return;
+                }
+                windowTapExcludeRegion.recycle();
                 WindowContainer parent = mDisplayContent.getParent();
                 if (parent != null && parent.getTopChild() != mDisplayContent) {
                     parent.positionChildAt(WindowContainer.POSITION_TOP, mDisplayContent,
@@ -81,9 +93,6 @@
 
     @Override
     public void onPointerEvent(MotionEvent motionEvent) {
-        if (motionEvent.getDisplayId() != getDisplayId()) {
-            return;
-        }
         switch (motionEvent.getActionMasked()) {
             case MotionEvent.ACTION_DOWN: {
                 final int x = (int) motionEvent.getX();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 752c24e..975e62a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6532,8 +6532,13 @@
 
     /**
      * Update a tap exclude region with a rectangular area in the window identified by the provided
-     * id. Touches on this region will not switch focus to this window. Passing an empty rect will
-     * remove the area from the exclude region of this window.
+     * id. Touches down on this region will not:
+     * <ol>
+     * <li>Switch focus to this window.</li>
+     * <li>Move the display of this window to top.</li>
+     * <li>Send the touch events to this window.</li>
+     * </ol>
+     * Passing an empty rect will remove the area from the exclude region of this window.
      */
     void updateTapExcludeRegion(IWindow client, int regionId, int left, int top, int width,
             int height) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4f12010..62e7200 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -536,7 +536,7 @@
     private final Point mSurfacePosition = new Point();
 
     /**
-     * A region inside of this window to be excluded from touch-related focus switches.
+     * A region inside of this window to be excluded from touch.
      */
     private TapExcludeRegionHolder mTapExcludeRegionHolder;
 
@@ -2168,6 +2168,24 @@
             }
             region.set(mTmpRect);
             cropRegionToStackBoundsIfNeeded(region);
+            subtractTouchExcludeRegionIfNeeded(region);
+        } else if (modal && mTapExcludeRegionHolder != null) {
+            final Region touchExcludeRegion = Region.obtain();
+            amendTapExcludeRegion(touchExcludeRegion);
+            if (!touchExcludeRegion.isEmpty()) {
+                // Remove touch modal because there are some areas that cannot be touched.
+                flags |= FLAG_NOT_TOUCH_MODAL;
+                // Give it a large touchable region at first because it was touch modal. The window
+                // might be moved on the display, so the touchable region should be large enough to
+                // ensure it covers the whole display, no matter where it is moved.
+                getDisplayContent().getBounds(mTmpRect);
+                final int dw = mTmpRect.width();
+                final int dh = mTmpRect.height();
+                region.set(-dw, -dh, dw + dw, dh + dh);
+                // Subtract the area that cannot be touched.
+                region.op(touchExcludeRegion, Region.Op.DIFFERENCE);
+            }
+            touchExcludeRegion.recycle();
         } else {
             // Not modal or full screen modal
             getTouchableRegion(region);
@@ -2837,6 +2855,7 @@
             }
         }
         cropRegionToStackBoundsIfNeeded(outRegion);
+        subtractTouchExcludeRegionIfNeeded(outRegion);
     }
 
     private void cropRegionToStackBoundsIfNeeded(Region region) {
@@ -2855,6 +2874,22 @@
     }
 
     /**
+     * If this window has areas that cannot be touched, we subtract those areas from its touchable
+     * region.
+     */
+    private void subtractTouchExcludeRegionIfNeeded(Region touchableRegion) {
+        if (mTapExcludeRegionHolder == null) {
+            return;
+        }
+        final Region touchExcludeRegion = Region.obtain();
+        amendTapExcludeRegion(touchExcludeRegion);
+        if (!touchExcludeRegion.isEmpty()) {
+            touchableRegion.op(touchExcludeRegion, Region.Op.DIFFERENCE);
+        }
+        touchExcludeRegion.recycle();
+    }
+
+    /**
      * Report a focus change.  Must be called with no locks held, and consistently
      * from the same serialized thread (such as dispatched from a handler).
      */
@@ -4728,11 +4763,25 @@
         mTapExcludeRegionHolder.updateRegion(regionId, left, top, width, height);
         // Trigger touch exclude region update on current display.
         currentDisplay.updateTouchExcludeRegion();
+        // Trigger touchable region update for this window.
+        currentDisplay.getInputMonitor().updateInputWindowsLw(true /* force */);
     }
 
-    /** Union the region with current tap exclude region that this window provides. */
+    /**
+     * Union the region with current tap exclude region that this window provides.
+     *
+     * @param region The region to be amended. It is on the screen coordinates.
+     */
     void amendTapExcludeRegion(Region region) {
-        mTapExcludeRegionHolder.amendRegion(region, getBounds());
+        final Region tempRegion = Region.obtain();
+        mTmpRect.set(mWindowFrames.mFrame);
+        mTmpRect.offsetTo(0, 0);
+        mTapExcludeRegionHolder.amendRegion(tempRegion, mTmpRect);
+        // The region held by the holder is on the window coordinates. We need to translate it to
+        // the screen coordinates.
+        tempRegion.translate(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top);
+        region.op(tempRegion, Region.Op.UNION);
+        tempRegion.recycle();
     }
 
     @Override
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index ff0b0d6..33317b5 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1652,6 +1652,13 @@
     im->setCustomPointerIcon(spriteIcon);
 }
 
+static jboolean nativeCanDispatchToDisplay(JNIEnv* env, jclass /* clazz */, jlong ptr,
+        jint deviceId, jint displayId) {
+
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+    return im->getInputManager()->getReader()->canDispatchToDisplay(deviceId, displayId);
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gInputManagerMethods[] = {
@@ -1726,6 +1733,8 @@
             (void*) nativeReloadPointerIcons },
     { "nativeSetCustomPointerIcon", "(JLandroid/view/PointerIcon;)V",
             (void*) nativeSetCustomPointerIcon },
+    { "nativeCanDispatchToDisplay", "(JII)Z",
+            (void*) nativeCanDispatchToDisplay },
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 51bdbb3..8f223b2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -74,20 +74,14 @@
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
 import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
-
 import static android.provider.Telephony.Carriers.DPC_URI;
 import static android.provider.Telephony.Carriers.ENFORCE_KEY;
 import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
 
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .PROVISIONING_ENTRY_POINT_ADB;
-import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker
-        .STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
-
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER;
 import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER;
-
-
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -240,11 +234,11 @@
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.util.JournaledFile;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.StatLogger;
 import com.android.internal.util.XmlUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
-import com.android.internal.util.StatLogger;
 import com.android.server.SystemServerInitThreadPool;
 import com.android.server.SystemService;
 import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
@@ -14207,7 +14201,8 @@
                         + "calendar APIs", packageName));
                 return false;
             }
-            final Intent intent = new Intent(CalendarContract.ACTION_VIEW_WORK_CALENDAR_EVENT);
+            final Intent intent = new Intent(
+                    CalendarContract.ACTION_VIEW_MANAGED_PROFILE_CALENDAR_EVENT);
             intent.setPackage(packageName);
             intent.putExtra(CalendarContract.EXTRA_EVENT_ID, eventId);
             intent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, start);
diff --git a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
new file mode 100644
index 0000000..33cbf7a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2019 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.rollback;
+
+import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.content.pm.VersionedPackage;
+import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.PackageRollbackInfo.RestoreInfo;
+import android.util.IntArray;
+
+import com.android.server.pm.Installer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+
+import java.io.File;
+import java.util.ArrayList;
+
+@RunWith(JUnit4.class)
+public class AppDataRollbackHelperTest {
+
+    @Test
+    public void testSnapshotAppData() throws Exception {
+        Installer installer = mock(Installer.class);
+        AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+
+        // All users are unlocked so we should snapshot data for them.
+        doReturn(true).when(helper).isUserCredentialLocked(eq(10));
+        doReturn(true).when(helper).isUserCredentialLocked(eq(11));
+        IntArray pending = helper.snapshotAppData("com.foo.bar", new int[]{10, 11});
+        assertEquals(2, pending.size());
+        assertEquals(10, pending.get(0));
+        assertEquals(11, pending.get(1));
+
+        InOrder inOrder = Mockito.inOrder(installer);
+        inOrder.verify(installer).snapshotAppData(
+                eq("com.foo.bar"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+        inOrder.verify(installer).snapshotAppData(
+                eq("com.foo.bar"), eq(11), eq(Installer.FLAG_STORAGE_DE));
+        inOrder.verifyNoMoreInteractions();
+
+        // One of the users is unlocked but the other isn't
+        doReturn(false).when(helper).isUserCredentialLocked(eq(10));
+        doReturn(true).when(helper).isUserCredentialLocked(eq(11));
+
+        pending = helper.snapshotAppData("com.foo.bar", new int[]{10, 11});
+        assertEquals(1, pending.size());
+        assertEquals(11, pending.get(0));
+
+        inOrder = Mockito.inOrder(installer);
+        inOrder.verify(installer).snapshotAppData(
+                eq("com.foo.bar"), eq(10),
+                eq(Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE));
+        inOrder.verify(installer).snapshotAppData(
+                eq("com.foo.bar"), eq(11), eq(Installer.FLAG_STORAGE_DE));
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    private static RollbackData createInProgressRollbackData(String packageName) {
+        RollbackData data = new RollbackData(1, new File("/does/not/exist"));
+        data.packages.add(new PackageRollbackInfo(
+                new VersionedPackage(packageName, 1), new VersionedPackage(packageName, 1),
+                new IntArray(), new ArrayList<>()));
+        data.inProgress = true;
+
+        return data;
+    }
+
+    @Test
+    public void testRestoreAppDataSnapshot_noRollbackData() throws Exception {
+        Installer installer = mock(Installer.class);
+        AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+
+        assertFalse(helper.restoreAppData("com.foo", null, 0, 0, 0, "seinfo"));
+        verifyZeroInteractions(installer);
+    }
+
+    @Test
+    public void testRestoreAppDataSnapshot_noRollbackInProgress() throws Exception {
+        Installer installer = mock(Installer.class);
+        AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+
+        RollbackData rd = createInProgressRollbackData("com.foo");
+        // Override the in progress flag.
+        rd.inProgress = false;
+        assertFalse(helper.restoreAppData("com.foo", rd, 0, 0, 0, "seinfo"));
+        verifyZeroInteractions(installer);
+    }
+
+    @Test
+    public void testRestoreAppDataSnapshot_pendingBackupForUser() throws Exception {
+        Installer installer = mock(Installer.class);
+        AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+
+        RollbackData rd = createInProgressRollbackData("com.foo");
+        IntArray pendingBackups = rd.packages.get(0).getPendingBackups();
+        pendingBackups.add(10);
+        pendingBackups.add(11);
+
+        assertTrue(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+
+        // Should only require FLAG_STORAGE_DE here because we have a pending backup that we
+        // didn't manage to execute.
+        InOrder inOrder = Mockito.inOrder(installer);
+        inOrder.verify(installer).restoreAppDataSnapshot(
+                eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+        inOrder.verifyNoMoreInteractions();
+
+        assertEquals(1, pendingBackups.size());
+        assertEquals(11, pendingBackups.get(0));
+    }
+
+    @Test
+    public void testRestoreAppDataSnapshot_availableBackupForLockedUser() throws Exception {
+        Installer installer = mock(Installer.class);
+        AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+        doReturn(true).when(helper).isUserCredentialLocked(eq(10));
+
+        RollbackData rd = createInProgressRollbackData("com.foo");
+
+        assertTrue(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+
+        InOrder inOrder = Mockito.inOrder(installer);
+        inOrder.verify(installer).restoreAppDataSnapshot(
+                eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+        inOrder.verifyNoMoreInteractions();
+
+        ArrayList<RestoreInfo> pendingRestores = rd.packages.get(0).getPendingRestores();
+        assertEquals(1, pendingRestores.size());
+        assertEquals(10, pendingRestores.get(0).userId);
+        assertEquals(1, pendingRestores.get(0).appId);
+        assertEquals("seinfo", pendingRestores.get(0).seInfo);
+    }
+
+    @Test
+    public void testRestoreAppDataSnapshot_availableBackupForUnockedUser() throws Exception {
+        Installer installer = mock(Installer.class);
+        AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+        doReturn(false).when(helper).isUserCredentialLocked(eq(10));
+
+        RollbackData rd = createInProgressRollbackData("com.foo");
+        assertFalse(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+
+        InOrder inOrder = Mockito.inOrder(installer);
+        inOrder.verify(installer).restoreAppDataSnapshot(
+                eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10),
+                eq(Installer.FLAG_STORAGE_DE | Installer.FLAG_STORAGE_CE));
+        inOrder.verifyNoMoreInteractions();
+
+        ArrayList<RestoreInfo> pendingRestores = rd.packages.get(0).getPendingRestores();
+        assertEquals(0, pendingRestores.size());
+    }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
index 1de1e4e..0b488c0 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.INotificationManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.IPackageManager;
@@ -36,22 +37,17 @@
 import android.util.IntArray;
 import android.util.Xml;
 
-import com.android.internal.util.FastXmlSerializer;
 import com.android.server.UiServiceTestCase;
 import com.android.server.notification.NotificationManagerService.NotificationAssistants;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlSerializer;
 
 import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -65,6 +61,8 @@
     private UserManager mUm;
     @Mock
     NotificationManagerService mNm;
+    @Mock
+    private INotificationManager mINm;
 
     NotificationAssistants mAssistants;
 
@@ -83,6 +81,7 @@
         getContext().setMockPackageManager(mPm);
         getContext().addMockSystemService(Context.USER_SERVICE, mUm);
         mAssistants = spy(mNm.new NotificationAssistants(getContext(), mLock, mUserProfiles, miPm));
+        when(mNm.getBinderService()).thenReturn(mINm);
 
         List<ResolveInfo> approved = new ArrayList<>();
         ResolveInfo resolve = new ResolveInfo();
@@ -136,4 +135,30 @@
         verify(mAssistants, times(1)).addApprovedList(
                 new ComponentName("b", "b").flattenToString(),10, true);
     }
+
+    @Test
+    public void testSetPackageOrComponentEnabled_onlyOnePackage() throws Exception {
+        ComponentName component1 = ComponentName.unflattenFromString("package/Component1");
+        ComponentName component2 = ComponentName.unflattenFromString("package/Component2");
+        mAssistants.setPackageOrComponentEnabled(component1.flattenToString(), mZero.id, true,
+                true);
+        verify(mINm, never()).setNotificationAssistantAccessGrantedForUser(any(ComponentName.class),
+                eq(mZero.id), anyBoolean());
+
+        mAssistants.setPackageOrComponentEnabled(component2.flattenToString(), mZero.id, true,
+                true);
+        verify(mINm, times(1)).setNotificationAssistantAccessGrantedForUser(component1, mZero.id,
+                false);
+    }
+
+    @Test
+    public void testSetPackageOrComponentEnabled_samePackage() throws Exception {
+        ComponentName component1 = ComponentName.unflattenFromString("package/Component1");
+        mAssistants.setPackageOrComponentEnabled(component1.flattenToString(), mZero.id, true,
+                true);
+        mAssistants.setPackageOrComponentEnabled(component1.flattenToString(), mZero.id, true,
+                true);
+        verify(mINm, never()).setNotificationAssistantAccessGrantedForUser(any(ComponentName.class),
+                eq(mZero.id), anyBoolean());
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 5d46f0f..4cae3b3 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2029,6 +2029,31 @@
     }
 
     @Test
+    public void testGetAssistantAllowedForUser() throws Exception {
+        UserHandle user = UserHandle.of(10);
+        try {
+            mBinderService.getAllowedNotificationAssistantForUser(user.getIdentifier());
+        } catch (IllegalStateException e) {
+            if (!e.getMessage().contains("At most one NotificationAssistant")) {
+                throw e;
+            }
+        }
+        verify(mAssistants, times(1)).getAllowedComponents(user.getIdentifier());
+    }
+
+    @Test
+    public void testGetAssistantAllowed() throws Exception {
+        try {
+            mBinderService.getAllowedNotificationAssistant();
+        } catch (IllegalStateException e) {
+            if (!e.getMessage().contains("At most one NotificationAssistant")) {
+                throw e;
+            }
+        }
+        verify(mAssistants, times(1)).getAllowedComponents(0);
+    }
+
+    @Test
     public void testSetDndAccessForUser() throws Exception {
         UserHandle user = UserHandle.of(10);
         ComponentName c = ComponentName.unflattenFromString("package/Component");
@@ -2089,6 +2114,54 @@
     }
 
     @Test
+    public void testSetAssistantAccess_nullWithAllowedAssistant() throws Exception {
+        ArrayList<ComponentName> componentList = new ArrayList<>();
+        ComponentName c = ComponentName.unflattenFromString("package/Component");
+        componentList.add(c);
+        when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
+
+        try {
+            mBinderService.setNotificationAssistantAccessGranted(null, true);
+        } catch (SecurityException e) {
+            if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
+                throw e;
+            }
+        }
+
+        verify(mAssistants, times(1)).setPackageOrComponentEnabled(
+                c.flattenToString(), 0, true, false);
+        verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
+                c.flattenToString(), 0, false,  false);
+        verify(mListeners, never()).setPackageOrComponentEnabled(
+                any(), anyInt(), anyBoolean(), anyBoolean());
+    }
+
+    @Test
+    public void testSetAssistantAccessForUser_nullWithAllowedAssistant() throws Exception {
+        UserHandle user = UserHandle.of(10);
+        ArrayList<ComponentName> componentList = new ArrayList<>();
+        ComponentName c = ComponentName.unflattenFromString("package/Component");
+        componentList.add(c);
+        when(mAssistants.getAllowedComponents(anyInt())).thenReturn(componentList);
+
+        try {
+            mBinderService.setNotificationAssistantAccessGrantedForUser(
+                    null, user.getIdentifier(), true);
+        } catch (SecurityException e) {
+            if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
+                throw e;
+            }
+        }
+
+        verify(mAssistants, times(1)).setPackageOrComponentEnabled(
+                c.flattenToString(), user.getIdentifier(), true, false);
+        verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
+                c.flattenToString(), user.getIdentifier(), false,  false);
+        verify(mListeners, never()).setPackageOrComponentEnabled(
+                any(), anyInt(), anyBoolean(), anyBoolean());
+    }
+
+    @Test
     public void testSetDndAccess() throws Exception {
         ComponentName c = ComponentName.unflattenFromString("package/Component");
         try {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index bde9dde..47ec390 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -2006,6 +2006,28 @@
     }
 
     @Test
+    public void testXml_statusBarIcons_default() throws Exception {
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        loadStreamXml(baos, false);
+
+        assertEquals(PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS,
+                mHelper.shouldHideSilentStatusIcons());
+    }
+
+    @Test
+    public void testXml_statusBarIcons() throws Exception {
+        mHelper.setHideSilentStatusIcons(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false);
+        mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
+        loadStreamXml(baos, false);
+
+        assertEquals(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS,
+                mHelper.shouldHideSilentStatusIcons());
+    }
+
+    @Test
     public void testSetNotificationDelegate() {
         mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53);
         assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 86af642..c1c598d 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.content.pm.VersionedPackage;
 import android.os.test.TestLooper;
 import android.support.test.InstrumentationRegistry;
 
@@ -47,6 +48,7 @@
     private static final String APP_B = "com.package.b";
     private static final String APP_C = "com.package.c";
     private static final String APP_D = "com.package.d";
+    private static final long VERSION_CODE = 1L;
     private static final String OBSERVER_NAME_1 = "observer1";
     private static final String OBSERVER_NAME_2 = "observer2";
     private static final String OBSERVER_NAME_3 = "observer3";
@@ -193,7 +195,7 @@
 
         // Then fail APP_A below the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT - 1; i++) {
-            watchdog.onPackageFailure(new String[]{APP_A});
+            watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
         }
 
         // Run handler so package failures are dispatched to observers
@@ -209,12 +211,10 @@
      * the failed packages.
      */
     @Test
-    public void testPackageFailureNotifyNone() throws Exception {
+    public void testPackageFailureDifferentPackageNotifyNone() throws Exception {
         PackageWatchdog watchdog = createWatchdog();
-        TestObserver observer1 = new TestObserver(OBSERVER_NAME_1,
-                PackageHealthObserverImpact.USER_IMPACT_HIGH);
-        TestObserver observer2 = new TestObserver(OBSERVER_NAME_2,
-                PackageHealthObserverImpact.USER_IMPACT_HIGH);
+        TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
+        TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
 
 
         watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION);
@@ -222,7 +222,7 @@
 
         // Then fail APP_C (not observed) above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
-            watchdog.onPackageFailure(new String[]{APP_C});
+            watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE)));
         }
 
         // Run handler so package failures are dispatched to observers
@@ -234,6 +234,40 @@
     }
 
     /**
+     * Test package failure and does not notify any observer because the failed package version
+     * does not match the available rollback-from-version.
+     */
+    @Test
+    public void testPackageFailureDifferentVersionNotifyNone() throws Exception {
+        PackageWatchdog watchdog = createWatchdog();
+        long differentVersionCode = 2L;
+        TestObserver observer = new TestObserver(OBSERVER_NAME_1) {
+                public int onHealthCheckFailed(String packageName, long versionCode) {
+                    if (versionCode == VERSION_CODE) {
+                        // Only rollback for specific versionCode
+                        return PackageHealthObserverImpact.USER_IMPACT_MEDIUM;
+                    }
+                    return PackageHealthObserverImpact.USER_IMPACT_NONE;
+                }
+            };
+
+        watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
+
+        // Then fail APP_A (different version) above the threshold
+        for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
+            watchdog.onPackageFailure(Arrays.asList(
+                            new VersionedPackage(APP_A, differentVersionCode)));
+        }
+
+        // Run handler so package failures are dispatched to observers
+        mTestLooper.dispatchAll();
+
+        // Verify that observers are not notified
+        assertEquals(0, observer.mFailedPackages.size());
+    }
+
+
+    /**
      * Test package failure and notifies only least impact observers.
      */
     @Test
@@ -260,7 +294,10 @@
 
         // Then fail all apps above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
-            watchdog.onPackageFailure(new String[]{APP_A, APP_B, APP_C, APP_D});
+            watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
+                    new VersionedPackage(APP_B, VERSION_CODE),
+                    new VersionedPackage(APP_C, VERSION_CODE),
+                    new VersionedPackage(APP_D, VERSION_CODE)));
         }
 
         // Run handler so package failures are dispatched to observers
@@ -297,7 +334,7 @@
      * <ul>
      */
     @Test
-    public void testPackageFailureNotifyLeastSuccessively() throws Exception {
+    public void testPackageFailureNotifyLeastImpactSuccessively() throws Exception {
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observerFirst = new TestObserver(OBSERVER_NAME_1,
                 PackageHealthObserverImpact.USER_IMPACT_LOW);
@@ -310,7 +347,7 @@
 
         // Then fail APP_A above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
-            watchdog.onPackageFailure(new String[]{APP_A});
+            watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
         }
         // Run handler so package failures are dispatched to observers
         mTestLooper.dispatchAll();
@@ -327,7 +364,7 @@
 
         // Then fail APP_A again above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
-            watchdog.onPackageFailure(new String[]{APP_A});
+            watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
         }
         // Run handler so package failures are dispatched to observers
         mTestLooper.dispatchAll();
@@ -344,7 +381,7 @@
 
         // Then fail APP_A again above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
-            watchdog.onPackageFailure(new String[]{APP_A});
+            watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
         }
         // Run handler so package failures are dispatched to observers
         mTestLooper.dispatchAll();
@@ -361,7 +398,7 @@
 
         // Then fail APP_A again above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
-            watchdog.onPackageFailure(new String[]{APP_A});
+            watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
         }
         // Run handler so package failures are dispatched to observers
         mTestLooper.dispatchAll();
@@ -388,7 +425,7 @@
 
         // Then fail APP_A above the threshold
         for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
-            watchdog.onPackageFailure(new String[]{APP_A});
+            watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
         }
 
         // Run handler so package failures are dispatched to observers
@@ -420,11 +457,11 @@
             mImpact = impact;
         }
 
-        public int onHealthCheckFailed(String packageName) {
+        public int onHealthCheckFailed(String packageName, long versionCode) {
             return mImpact;
         }
 
-        public boolean execute(String packageName) {
+        public boolean execute(String packageName, long versionCode) {
             mFailedPackages.add(packageName);
             return true;
         }
diff --git a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java
index 02a439b..2310c82 100644
--- a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java
+++ b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java
@@ -17,17 +17,30 @@
 package com.android.tests.rollback.testapp;
 
 import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
 import android.os.Bundle;
 
 /**
  * A crashing test app for testing apk rollback support.
  */
 public class CrashingMainActivity extends Activity {
-
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
+        incrementCountAndBroadcast();
         throw new RuntimeException("Intended force crash");
     }
+
+    public void incrementCountAndBroadcast() {
+        SharedPreferences preferences = getSharedPreferences("prefs", Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = preferences.edit();
+        int count = preferences.getInt("crash_count", 0);
+        editor.putInt("crash_count", ++count).commit();
+
+        Intent intent = new Intent("com.android.tests.rollback.CRASH");
+        intent.putExtra("count", count);
+        sendBroadcast(intent);
+    }
 }
diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index e128a6c..4b277ae 100644
--- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -17,6 +17,7 @@
 package com.android.tests.rollback;
 
 import android.Manifest;
+import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -36,7 +37,6 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -45,6 +45,7 @@
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -413,7 +414,6 @@
 
     /**
      * Test that app user data is rolled back.
-     * TODO: Stop ignoring this test once user data rollback is supported.
      */
     @Test
     public void testUserDataRollback() throws Exception {
@@ -568,9 +568,7 @@
     }
 
     /**
-     * Test rollback of multi-package installs.
-     * TODO: Stop ignoring this test once support for multi-package rollback
-     * is implemented.
+     * Test rollback of multi-package installs is implemented.
      */
     @Test
     public void testMultiPackage() throws Exception {
@@ -630,18 +628,20 @@
         assertEquals(versionRolledBackTo, info.getVersionRolledBackTo().getLongVersionCode());
     }
 
-    // TODO(zezeozue): Stop ignoring after fixing race between rolling back and testing version
     /**
      * Test bad update automatic rollback.
      */
-    @Ignore("Flaky")
     @Test
     public void testBadUpdateRollback() throws Exception {
+        BroadcastReceiver crashCountReceiver = null;
+        Context context = InstrumentationRegistry.getContext();
         try {
             RollbackTestUtils.adoptShellPermissionIdentity(
                     Manifest.permission.INSTALL_PACKAGES,
                     Manifest.permission.DELETE_PACKAGES,
-                    Manifest.permission.MANAGE_ROLLBACKS);
+                    Manifest.permission.MANAGE_ROLLBACKS,
+                    Manifest.permission.KILL_BACKGROUND_PROCESSES,
+                    Manifest.permission.RESTART_PACKAGES);
             RollbackManager rm = RollbackTestUtils.getRollbackManager();
 
             // Prep installation of the test apps.
@@ -669,23 +669,52 @@
                     rm.getAvailableRollbacks(), TEST_APP_B);
             assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB);
 
+            BlockingQueue<Integer> crashQueue = new SynchronousQueue<>();
+
+            IntentFilter crashCountFilter = new IntentFilter();
+            crashCountFilter.addAction("com.android.tests.rollback.CRASH");
+            crashCountFilter.addCategory(Intent.CATEGORY_DEFAULT);
+
+            crashCountReceiver = new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        try {
+                            // Sleep long enough for packagewatchdog to be notified of crash
+                            Thread.sleep(1000);
+                            // Kill app and close AppErrorDialog
+                            ActivityManager am = context.getSystemService(ActivityManager.class);
+                            am.killBackgroundProcesses(TEST_APP_A);
+                            // Allow another package launch
+                            crashQueue.offer(intent.getIntExtra("count", 0), 5, TimeUnit.SECONDS);
+                        } catch (InterruptedException e) {
+                            fail("Failed to communicate with test app");
+                        }
+                    }
+                };
+            context.registerReceiver(crashCountReceiver, crashCountFilter);
+
             // Start apps PackageWatchdog#TRIGGER_FAILURE_COUNT times so TEST_APP_A crashes
-            for (int i = 0; i < 5; i++) {
+            Integer crashCount = null;
+            do {
                 RollbackTestUtils.launchPackage(TEST_APP_A);
-                Thread.sleep(1000);
-            }
-            Thread.sleep(1000);
+                crashCount = crashQueue.poll(5, TimeUnit.SECONDS);
+                if (crashCount == null) {
+                    fail("Timed out waiting for crash signal from test app");
+                }
+            } while(crashCount < 5);
 
             // TEST_APP_A is automatically rolled back by the RollbackPackageHealthObserver
             assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
             // Instrumented app is still the package installer
-            Context context = InstrumentationRegistry.getContext();
             String installer = context.getPackageManager().getInstallerPackageName(TEST_APP_A);
             assertEquals(INSTRUMENTED_APP, installer);
             // TEST_APP_B is untouched
             assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B));
         } finally {
             RollbackTestUtils.dropShellPermissionIdentity();
+            if (crashCountReceiver != null) {
+                context.unregisterReceiver(crashCountReceiver);
+            }
         }
     }
 
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 17847ea..145e269 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -23,17 +23,9 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import java.io.ByteArrayInputStream;
 import java.nio.charset.StandardCharsets;
-import java.security.KeyFactory;
-import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -1126,6 +1118,12 @@
             String value = PASSWORD_KEY.equals(key) ? "<removed>" : mFields.get(key);
             sb.append(key).append(" ").append(value).append("\n");
         }
+        if (mEapMethod >= 0 && mEapMethod < Eap.strings.length) {
+            sb.append("eap_method: ").append(Eap.strings[mEapMethod]).append("\n");
+        }
+        if (mPhase2Method > 0 && mPhase2Method < Phase2.strings.length) {
+            sb.append("phase2_method: ").append(Phase2.strings[mPhase2Method]).append("\n");
+        }
         return sb.toString();
     }