Merge "Add Dvbc Frontend Bandwidth Settings"
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
index 5f2fabe..beb9ad3 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
@@ -27,8 +27,6 @@
  *
  * <p>This class is a higher level implement of {@link GenericDocument}.
  *
- * <p>This class will eventually migrate to Jetpack, where it will become public API.
- *
  * @hide
  */
 
@@ -99,10 +97,9 @@
     }
 
     /**
-     * Get the from address of {@link AppSearchEmail}.
+     * Gets the from address of {@link AppSearchEmail}.
      *
-     * @return Returns the subject of {@link AppSearchEmail} or {@code null} if it's not been set
-     *         yet.
+     * @return The subject of {@link AppSearchEmail} or {@code null} if it's not been set yet.
      */
     @Nullable
     public String getFrom() {
@@ -110,10 +107,10 @@
     }
 
     /**
-     * Get the destination addresses of {@link AppSearchEmail}.
+     * Gets the destination addresses of {@link AppSearchEmail}.
      *
-     * @return Returns the destination addresses of {@link AppSearchEmail} or {@code null} if it's
-     *         not been set yet.
+     * @return The destination addresses of {@link AppSearchEmail} or {@code null} if it's not
+     *         been set yet.
      */
     @Nullable
     public String[] getTo() {
@@ -121,10 +118,9 @@
     }
 
     /**
-     * Get the CC list of {@link AppSearchEmail}.
+     * Gets the CC list of {@link AppSearchEmail}.
      *
-     * @return Returns the CC list of {@link AppSearchEmail} or {@code null} if it's not been set
-     *         yet.
+     * @return The CC list of {@link AppSearchEmail} or {@code null} if it's not been set yet.
      */
     @Nullable
     public String[] getCc() {
@@ -132,10 +128,9 @@
     }
 
     /**
-     * Get the BCC list of {@link AppSearchEmail}.
+     * Gets the BCC list of {@link AppSearchEmail}.
      *
-     * @return Returns the BCC list of {@link AppSearchEmail} or {@code null} if it's not been set
-     *         yet.
+     * @return The BCC list of {@link AppSearchEmail} or {@code null} if it's not been set yet.
      */
     @Nullable
     public String[] getBcc() {
@@ -143,10 +138,9 @@
     }
 
     /**
-     * Get the subject of {@link AppSearchEmail}.
+     * Gets the subject of {@link AppSearchEmail}.
      *
-     * @return Returns the value subject of {@link AppSearchEmail} or {@code null} if it's not been
-     *         set yet.
+     * @return The value subject of {@link AppSearchEmail} or {@code null} if it's not been set yet.
      */
     @Nullable
     public String getSubject() {
@@ -154,9 +148,9 @@
     }
 
     /**
-     * Get the body of {@link AppSearchEmail}.
+     * Gets the body of {@link AppSearchEmail}.
      *
-     * @return Returns the body of {@link AppSearchEmail} or {@code null} if it's not been set yet.
+     * @return The body of {@link AppSearchEmail} or {@code null} if it's not been set yet.
      */
     @Nullable
     public String getBody() {
@@ -169,7 +163,8 @@
     public static class Builder extends GenericDocument.Builder<AppSearchEmail.Builder> {
 
         /**
-         * Create a new {@link AppSearchEmail.Builder}
+         * Creates a new {@link AppSearchEmail.Builder}
+         *
          * @param uri The Uri of the Email.
          */
         public Builder(@NonNull String uri) {
@@ -177,56 +172,56 @@
         }
 
         /**
-         * Set the from address of {@link AppSearchEmail}
+         * Sets the from address of {@link AppSearchEmail}
          */
         @NonNull
         public AppSearchEmail.Builder setFrom(@NonNull String from) {
-            setProperty(KEY_FROM, from);
+            setPropertyString(KEY_FROM, from);
             return this;
         }
 
         /**
-         * Set the destination address of {@link AppSearchEmail}
+         * Sets the destination address of {@link AppSearchEmail}
          */
         @NonNull
         public AppSearchEmail.Builder setTo(@NonNull String... to) {
-            setProperty(KEY_TO, to);
+            setPropertyString(KEY_TO, to);
             return this;
         }
 
         /**
-         * Set the CC list of {@link AppSearchEmail}
+         * Sets the CC list of {@link AppSearchEmail}
          */
         @NonNull
         public AppSearchEmail.Builder setCc(@NonNull String... cc) {
-            setProperty(KEY_CC, cc);
+            setPropertyString(KEY_CC, cc);
             return this;
         }
 
         /**
-         * Set the BCC list of {@link AppSearchEmail}
+         * Sets the BCC list of {@link AppSearchEmail}
          */
         @NonNull
         public AppSearchEmail.Builder setBcc(@NonNull String... bcc) {
-            setProperty(KEY_BCC, bcc);
+            setPropertyString(KEY_BCC, bcc);
             return this;
         }
 
         /**
-         * Set the subject of {@link AppSearchEmail}
+         * Sets the subject of {@link AppSearchEmail}
          */
         @NonNull
         public AppSearchEmail.Builder setSubject(@NonNull String subject) {
-            setProperty(KEY_SUBJECT, subject);
+            setPropertyString(KEY_SUBJECT, subject);
             return this;
         }
 
         /**
-         * Set the body of {@link AppSearchEmail}
+         * Sets the body of {@link AppSearchEmail}
          */
         @NonNull
         public AppSearchEmail.Builder setBody(@NonNull String body) {
-            setProperty(KEY_BODY, body);
+            setPropertyString(KEY_BODY, body);
             return this;
         }
 
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java
index 90e4df6..3933726 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java
@@ -16,10 +16,12 @@
 
 package android.app.appsearch;
 
+import android.annotation.SuppressLint;
 import android.os.Bundle;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 
 import android.app.appsearch.exceptions.IllegalSchemaException;
 import android.util.ArraySet;
@@ -28,6 +30,8 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -39,13 +43,8 @@
  * @hide
  */
 public final class AppSearchSchema {
-    /** @hide */
-    
-    public static final String SCHEMA_TYPE_FIELD = "schemaType";
-
-    /** @hide */
-    
-    public static final String PROPERTIES_FIELD = "properties";
+    private static final String SCHEMA_TYPE_FIELD = "schemaType";
+    private static final String PROPERTIES_FIELD = "properties";
 
     private final Bundle mBundle;
 
@@ -71,10 +70,35 @@
         return mBundle.toString();
     }
 
+    /** Returns the name of this schema type, e.g. Email. */
+    @NonNull
+    public String getSchemaTypeName() {
+        return mBundle.getString(SCHEMA_TYPE_FIELD, "");
+    }
+
+    /**
+     * Returns the list of {@link PropertyConfig}s that are part of this schema.
+     *
+     * <p>This method creates a new list when called.
+     */
+    @NonNull
+    public List<PropertyConfig> getProperties() {
+        ArrayList<Bundle> propertyBundles =
+                mBundle.getParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD);
+        if (propertyBundles.isEmpty()) {
+            return Collections.emptyList();
+        }
+        List<PropertyConfig> ret = new ArrayList<>(propertyBundles.size());
+        for (int i = 0; i < propertyBundles.size(); i++) {
+            ret.add(new PropertyConfig(propertyBundles.get(i)));
+        }
+        return ret;
+    }
+
     /** Builder for {@link AppSearchSchema objects}. */
     public static final class Builder {
         private final String mTypeName;
-        private final ArrayList<Bundle> mProperties = new ArrayList<>();
+        private final ArrayList<Bundle> mPropertyBundles = new ArrayList<>();
         private final Set<String> mPropertyNames = new ArraySet<>();
         private boolean mBuilt = false;
 
@@ -85,15 +109,19 @@
         }
 
         /** Adds a property to the given type. */
+        // TODO(b/171360120): MissingGetterMatchingBuilder expects a method called getPropertys, but
+        //  we provide the (correct) method getProperties. Once the bug referenced in this TODO is
+        //  fixed, remove this SuppressLint.
+        @SuppressLint("MissingGetterMatchingBuilder")
         @NonNull
         public AppSearchSchema.Builder addProperty(@NonNull PropertyConfig propertyConfig) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkNotNull(propertyConfig);
-            if (!mPropertyNames.add(propertyConfig.mName)) {
-                throw new IllegalSchemaException(
-                        "Property defined more than once: " + propertyConfig.mName);
+            String name = propertyConfig.getName();
+            if (!mPropertyNames.add(name)) {
+                throw new IllegalSchemaException("Property defined more than once: " + name);
             }
-            mProperties.add(propertyConfig.mBundle);
+            mPropertyBundles.add(propertyConfig.mBundle);
             return this;
         }
 
@@ -107,7 +135,7 @@
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Bundle bundle = new Bundle();
             bundle.putString(AppSearchSchema.SCHEMA_TYPE_FIELD, mTypeName);
-            bundle.putParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD, mProperties);
+            bundle.putParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD, mPropertyBundles);
             mBuilt = true;
             return new AppSearchSchema(bundle);
         }
@@ -120,29 +148,12 @@
      * a property.
      */
     public static final class PropertyConfig {
-        /** @hide */
-        
-        public static final String NAME_FIELD = "name";
-
-        /** @hide */
-        
-        public static final String DATA_TYPE_FIELD = "dataType";
-
-        /** @hide */
-        
-        public static final String SCHEMA_TYPE_FIELD = "schemaType";
-
-        /** @hide */
-        
-        public static final String CARDINALITY_FIELD = "cardinality";
-
-        /** @hide */
-        
-        public static final String INDEXING_TYPE_FIELD = "indexingType";
-
-        /** @hide */
-        
-        public static final String TOKENIZER_TYPE_FIELD = "tokenizerType";
+        private static final String NAME_FIELD = "name";
+        private static final String DATA_TYPE_FIELD = "dataType";
+        private static final String SCHEMA_TYPE_FIELD = "schemaType";
+        private static final String CARDINALITY_FIELD = "cardinality";
+        private static final String INDEXING_TYPE_FIELD = "indexingType";
+        private static final String TOKENIZER_TYPE_FIELD = "tokenizerType";
 
         /**
          * Physical data-types of the contents of the property.
@@ -259,11 +270,9 @@
         /** Tokenization for plain text. */
         public static final int TOKENIZER_TYPE_PLAIN = 1;
 
-        final String mName;
         final Bundle mBundle;
 
-        PropertyConfig(@NonNull String name, @NonNull Bundle bundle) {
-            mName = Preconditions.checkNotNull(name);
+        PropertyConfig(@NonNull Bundle bundle) {
             mBundle = Preconditions.checkNotNull(bundle);
         }
 
@@ -272,6 +281,45 @@
             return mBundle.toString();
         }
 
+        /** Returns the name of this property. */
+        @NonNull
+        public String getName() {
+            return mBundle.getString(NAME_FIELD, "");
+        }
+
+        /** Returns the type of data the property contains (e.g. string, int, bytes, etc). */
+        public @DataType int getDataType() {
+            return mBundle.getInt(DATA_TYPE_FIELD, -1);
+        }
+
+        /**
+         * Returns the logical schema-type of the contents of this property.
+         *
+         * <p>Only set when {@link #getDataType} is set to {@link #DATA_TYPE_DOCUMENT}.
+         * Otherwise, it is {@code null}.
+         */
+        @Nullable
+        public String getSchemaType() {
+            return mBundle.getString(SCHEMA_TYPE_FIELD);
+        }
+
+        /**
+         * Returns the cardinality of the property (whether it is optional, required or repeated).
+         */
+        public @Cardinality int getCardinality() {
+            return mBundle.getInt(CARDINALITY_FIELD, -1);
+        }
+
+        /** Returns how the property is indexed. */
+        public @IndexingType int getIndexingType() {
+            return mBundle.getInt(INDEXING_TYPE_FIELD);
+        }
+
+        /** Returns how this property is tokenized (split into words). */
+        public @TokenizerType int getTokenizerType() {
+            return mBundle.getInt(TOKENIZER_TYPE_FIELD);
+        }
+
         /**
          * Builder for {@link PropertyConfig}.
          *
@@ -286,13 +334,11 @@
          * is also required.
          */
         public static final class Builder {
-            private final String mName;
             private final Bundle mBundle = new Bundle();
             private boolean mBuilt = false;
 
             /** Creates a new {@link PropertyConfig.Builder}. */
             public Builder(@NonNull String propertyName) {
-                mName = Preconditions.checkNotNull(propertyName);
                 mBundle.putString(NAME_FIELD, propertyName);
             }
 
@@ -386,7 +432,7 @@
                     throw new IllegalSchemaException("Missing field: cardinality");
                 }
                 mBuilt = true;
-                return new PropertyConfig(mName, mBundle);
+                return new PropertyConfig(mBundle);
             }
         }
     }
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java
index 9fe2c67..48d3ac0 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java
@@ -30,6 +30,7 @@
 import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Set;
 
 /**
@@ -65,20 +66,14 @@
     /** The default time-to-live in millisecond of a document, which is infinity. */
     private static final long DEFAULT_TTL_MILLIS = 0L;
 
-    /** @hide */
-    
-    public static final String PROPERTIES_FIELD = "properties";
-
-    /** @hide */
-    
-    public static final String BYTE_ARRAY_FIELD = "byteArray";
-
-    static final String SCHEMA_TYPE_FIELD = "schemaType";
-    static final String URI_FIELD = "uri";
-    static final String SCORE_FIELD = "score";
-    static final String TTL_MILLIS_FIELD = "ttlMillis";
-    static final String CREATION_TIMESTAMP_MILLIS_FIELD = "creationTimestampMillis";
-    static final String NAMESPACE_FIELD = "namespace";
+    private static final String PROPERTIES_FIELD = "properties";
+    private static final String BYTE_ARRAY_FIELD = "byteArray";
+    private static final String SCHEMA_TYPE_FIELD = "schemaType";
+    private static final String URI_FIELD = "uri";
+    private static final String SCORE_FIELD = "score";
+    private static final String TTL_MILLIS_FIELD = "ttlMillis";
+    private static final String CREATION_TIMESTAMP_MILLIS_FIELD = "creationTimestampMillis";
+    private static final String NAMESPACE_FIELD = "namespace";
 
     /**
      * The maximum number of indexed properties a document can have.
@@ -190,6 +185,12 @@
         return mBundle.getInt(SCORE_FIELD, DEFAULT_SCORE);
     }
 
+    /** Returns the names of all properties defined in this document. */
+    @NonNull
+    public Set<String> getPropertyNames() {
+        return Collections.unmodifiableSet(mProperties.keySet());
+    }
+
     /**
      * Retrieves a {@link String} value by key.
      *
@@ -437,8 +438,6 @@
 
     @Override
     public boolean equals(@Nullable Object other) {
-        // Check only proto's equality is sufficient here since all properties in
-        // mProperties are ordered by keys and stored in proto.
         if (this == other) {
             return true;
         }
@@ -450,8 +449,8 @@
     }
 
     /**
-     * Deeply checks two bundle is equally or not.
-     * <p> Two bundle will be considered equally if they contains same content.
+     * Deeply checks two bundles are equally or not.
+     * <p> Two bundles will be considered equally if they contain same content.
      */
     @SuppressWarnings("unchecked")
     private static boolean bundleEquals(Bundle one, Bundle two) {
@@ -472,7 +471,7 @@
                 return false;
             } else if (valueOne == null && (valueTwo != null || !two.containsKey(key))) {
                 // If we call bundle.get(key) when the 'key' doesn't actually exist in the
-                // bundle, we'll get  back a null. So make sure that both values are null and
+                // bundle, we'll get back a null. So make sure that both values are null and
                 // both keys exist in the bundle.
                 return false;
             } else if (valueOne instanceof boolean[]) {
@@ -538,8 +537,8 @@
 
     /**
      * Calculates the hash code for a bundle.
-     * <p> The hash code is only effected by the content in the bundle. Bundles will get
-     * consistent hash code if they have same content.
+     * <p> The hash code is only effected by the contents in the bundle. Bundles will get
+     * consistent hash code if they have same contents.
      */
     @SuppressWarnings("unchecked")
     private static int bundleHashCode(Bundle bundle) {
@@ -648,8 +647,11 @@
     /**
      * The builder class for {@link GenericDocument}.
      *
-     * @param <BuilderType> Type of subclass who extend this.
+     * @param <BuilderType> Type of subclass who extends this.
      */
+    // This builder is specifically designed to be extended by classes deriving from
+    // GenericDocument.
+    @SuppressLint("StaticFinalBuilder")
     public static class Builder<BuilderType extends Builder> {
 
         private final Bundle mProperties = new Bundle();
@@ -662,12 +664,11 @@
          *
          * @param uri The uri of {@link GenericDocument}.
          * @param schemaType The schema type of the {@link GenericDocument}. The passed-in
-         *        {@code schemaType} must be defined using {@code AppSearchManager#setSchema} prior
+         *        {@code schemaType} must be defined using {@link AppSearchSession#setSchema} prior
          *        to inserting a document of this {@code schemaType} into the AppSearch index using
-         *        {@code AppSearchManager#putDocuments}. Otherwise, the document will be
-         *        rejected by {@code AppSearchManager#putDocuments}.
+         *        {@link AppSearchSession#putDocuments}. Otherwise, the document will be
+         *        rejected by {@link AppSearchSession#putDocuments}.
          */
-        //TODO(b/157082794) Linkify AppSearchManager once that API is public.
         @SuppressWarnings("unchecked")
         public Builder(@NonNull String uri, @NonNull String schemaType) {
             Preconditions.checkNotNull(uri);
@@ -685,9 +686,12 @@
         }
 
         /**
-         * Set the app-defined namespace this Document resides in. No special values  are
-         * reserved or understood by the infrastructure. URIs are unique within a namespace. The
-         * number of namespaces per app should be kept small for efficiency reasons.
+         * Sets the app-defined namespace this Document resides in. No special values are
+         * reserved or understood by the infrastructure.
+         *
+         * <p>URIs are unique within a namespace.
+         *
+         * <p>The number of namespaces per app should be kept small for efficiency reasons.
          */
         @NonNull
         public BuilderType setNamespace(@NonNull String namespace) {
@@ -714,7 +718,7 @@
         }
 
         /**
-         * Set the creation timestamp in milliseconds of the {@link GenericDocument}. Should be
+         * Sets the creation timestamp of the {@link GenericDocument}, in milliseconds. Should be
          * set using a value obtained from the {@link System#currentTimeMillis()} time base.
          */
         @NonNull
@@ -726,7 +730,7 @@
         }
 
         /**
-         * Set the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds.
+         * Sets the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds.
          *
          * <p>After this many milliseconds since the {@link #setCreationTimestampMillis creation
          * timestamp}, the document is deleted.
@@ -752,7 +756,7 @@
          * @param values The {@code String} values of the property.
          */
         @NonNull
-        public BuilderType setProperty(@NonNull String key, @NonNull String... values) {
+        public BuilderType setPropertyString(@NonNull String key, @NonNull String... values) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkNotNull(key);
             Preconditions.checkNotNull(values);
@@ -768,7 +772,7 @@
          * @param values The {@code boolean} values of the property.
          */
         @NonNull
-        public BuilderType setProperty(@NonNull String key, @NonNull boolean... values) {
+        public BuilderType setPropertyBoolean(@NonNull String key, @NonNull boolean... values) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkNotNull(key);
             Preconditions.checkNotNull(values);
@@ -784,7 +788,7 @@
          * @param values The {@code long} values of the property.
          */
         @NonNull
-        public BuilderType setProperty(@NonNull String key, @NonNull long... values) {
+        public BuilderType setPropertyLong(@NonNull String key, @NonNull long... values) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkNotNull(key);
             Preconditions.checkNotNull(values);
@@ -800,7 +804,7 @@
          * @param values The {@code double} values of the property.
          */
         @NonNull
-        public BuilderType setProperty(@NonNull String key, @NonNull double... values) {
+        public BuilderType setPropertyDouble(@NonNull String key, @NonNull double... values) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkNotNull(key);
             Preconditions.checkNotNull(values);
@@ -815,7 +819,7 @@
          * @param values The {@code byte[]} of the property.
          */
         @NonNull
-        public BuilderType setProperty(@NonNull String key, @NonNull byte[]... values) {
+        public BuilderType setPropertyBytes(@NonNull String key, @NonNull byte[]... values) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkNotNull(key);
             Preconditions.checkNotNull(values);
@@ -831,7 +835,8 @@
          * @param values The {@link GenericDocument} values of the property.
          */
         @NonNull
-        public BuilderType setProperty(@NonNull String key, @NonNull GenericDocument... values) {
+        public BuilderType setPropertyDocument(
+                @NonNull String key, @NonNull GenericDocument... values) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkNotNull(key);
             Preconditions.checkNotNull(values);
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
index 3c0e746..e1e0eda 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
@@ -17,12 +17,12 @@
 package android.app.appsearch;
 
 import android.annotation.NonNull;
-
 import android.util.ArraySet;
 import com.android.internal.util.Preconditions;
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Set;
 
 /**
@@ -40,18 +40,16 @@
         mUris = uris;
     }
 
-    /** @hide */
-    
+    /** Returns the namespace to get documents from. */
     @NonNull
     public String getNamespace() {
         return mNamespace;
     }
 
-    /** @hide */
-    
+    /** Returns the URIs to get from the namespace. */
     @NonNull
     public Set<String> getUris() {
-        return mUris;
+        return Collections.unmodifiableSet(mUris);
     }
 
     /** Builder for {@link GetByUriRequest} objects. */
@@ -75,14 +73,14 @@
 
         /** Adds one or more URIs to the request. */
         @NonNull
-        public Builder addUris(@NonNull String... uris) {
+        public Builder addUri(@NonNull String... uris) {
             Preconditions.checkNotNull(uris);
-            return addUris(Arrays.asList(uris));
+            return addUri(Arrays.asList(uris));
         }
 
         /** Adds one or more URIs to the request. */
         @NonNull
-        public Builder addUris(@NonNull Collection<String> uris) {
+        public Builder addUri(@NonNull Collection<String> uris) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkNotNull(uris);
             mUris.addAll(uris);
diff --git a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
index 7e97542..1f90bc1 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
@@ -16,13 +16,16 @@
 
 package android.app.appsearch;
 
-import android.annotation.NonNull;
+import android.annotation.SuppressLint;
 
+import android.annotation.NonNull;
+import android.app.appsearch.exceptions.AppSearchException;
 import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -38,11 +41,10 @@
         mDocuments = documents;
     }
 
-    /** @hide */
-    
+    /** Returns the documents that are part of this request. */
     @NonNull
     public List<GenericDocument> getDocuments() {
-        return mDocuments;
+        return Collections.unmodifiableList(mDocuments);
     }
 
     /** Builder for {@link PutDocumentsRequest} objects. */
@@ -51,6 +53,7 @@
         private boolean mBuilt = false;
 
         /** Adds one or more documents to the request. */
+        @SuppressLint("MissingGetterMatchingBuilder")  // Merged list available from getDocuments()
         @NonNull
         public Builder addGenericDocument(@NonNull GenericDocument... documents) {
             Preconditions.checkNotNull(documents);
@@ -58,6 +61,7 @@
         }
 
         /** Adds one or more documents to the request. */
+        @SuppressLint("MissingGetterMatchingBuilder")  // Merged list available from getDocuments()
         @NonNull
         public Builder addGenericDocument(@NonNull Collection<GenericDocument> documents) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
diff --git a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
index a047041..486857f 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
@@ -17,12 +17,12 @@
 package android.app.appsearch;
 
 import android.annotation.NonNull;
-
 import android.util.ArraySet;
 import com.android.internal.util.Preconditions;
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Set;
 
 /**
@@ -40,18 +40,16 @@
         mUris = uris;
     }
 
-    /** @hide */
-    
+    /** Returns the namespace to remove documents from. */
     @NonNull
     public String getNamespace() {
         return mNamespace;
     }
 
-    /** @hide */
-    
+    /** Returns the URIs to remove from the namespace. */
     @NonNull
     public Set<String> getUris() {
-        return mUris;
+        return Collections.unmodifiableSet(mUris);
     }
 
     /** Builder for {@link RemoveByUriRequest} objects. */
@@ -75,14 +73,14 @@
 
         /** Adds one or more URIs to the request. */
         @NonNull
-        public Builder addUris(@NonNull String... uris) {
+        public Builder addUri(@NonNull String... uris) {
             Preconditions.checkNotNull(uris);
-            return addUris(Arrays.asList(uris));
+            return addUri(Arrays.asList(uris));
         }
 
         /** Adds one or more URIs to the request. */
         @NonNull
-        public Builder addUris(@NonNull Collection<String> uris) {
+        public Builder addUri(@NonNull Collection<String> uris) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkNotNull(uris);
             mUris.addAll(uris);
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java
index 758280b..99cb2f1 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java
@@ -49,19 +49,22 @@
     @NonNull
     private final Bundle mDocumentBundle;
 
+    /** Cache of the inflated document. Comes from inflating mDocumentBundle at first use. */
     @Nullable
     private GenericDocument mDocument;
 
-    @Nullable
-    private final List<Bundle> mMatchBundles;
-
     /**
-     * Contains a list of Snippets that matched the request. Only populated when requested in
-     * both {@link SearchSpec.Builder#setSnippetCount(int)}
-     * and {@link SearchSpec.Builder#setSnippetCountPerProperty(int)}.
+     * Contains a list of MatchInfo bundles that matched the request.
+     *
+     * Only populated when requested in both {@link SearchSpec.Builder#setSnippetCount} and
+     * {@link SearchSpec.Builder#setSnippetCountPerProperty}.
      *
      * @see #getMatches()
      */
+    @NonNull
+    private final List<Bundle> mMatchBundles;
+
+    /** Cache of the inflated matches. Comes from inflating mMatchBundles at first use. */
     @Nullable
     private List<MatchInfo> mMatches;
 
@@ -70,7 +73,7 @@
     public SearchResult(@NonNull Bundle bundle) {
         mBundle = Preconditions.checkNotNull(bundle);
         mDocumentBundle = Preconditions.checkNotNull(bundle.getBundle(DOCUMENT_FIELD));
-        mMatchBundles = bundle.getParcelableArrayList(MATCHES_FIELD);
+        mMatchBundles = Preconditions.checkNotNull(bundle.getParcelableArrayList(MATCHES_FIELD));
     }
 
     /** @hide */
@@ -93,19 +96,16 @@
     }
 
     /**
-     * Contains a list of Snippets that matched the request. Only populated when requested in
-     * both {@link SearchSpec.Builder#setSnippetCount(int)}
-     * and {@link SearchSpec.Builder#setSnippetCountPerProperty(int)}.
+     * Contains a list of Snippets that matched the request.
      *
-     * @return  List of matches based on {@link SearchSpec}, if snippeting is disabled and this
-     * method is called it will return {@code null}. Users can also restrict snippet population
-     * using {@link SearchSpec.Builder#setSnippetCount} and
-     * {@link SearchSpec.Builder#setSnippetCountPerProperty(int)}, for all results after that
-     * value this method will return {@code null}.
+     * @return List of matches based on {@link SearchSpec}. If snippeting is disabled using
+     * {@link SearchSpec.Builder#setSnippetCount} or
+     * {@link SearchSpec.Builder#setSnippetCountPerProperty}, for all results after that
+     * value, this method returns an empty list.
      */
-    @Nullable
+    @NonNull
     public List<MatchInfo> getMatches() {
-        if (mMatchBundles != null && mMatches == null) {
+        if (mMatches == null) {
             mMatches = new ArrayList<>(mMatchBundles.size());
             for (int i = 0; i < mMatchBundles.size(); i++) {
                 MatchInfo matchInfo = new MatchInfo(getDocument(), mMatchBundles.get(i));
@@ -119,8 +119,8 @@
      * Snippet: It refers to a substring of text from the content of document that is returned as a
      * part of search result.
      * This class represents a match objects for any Snippets that might be present in
-     * {@link SearchResults} from query. Using this class user can get the full text, exact matches
-     * and Snippets of document content for a given match.
+     * {@link SearchResults} from query. Using this class
+     * user can get the full text, exact matches and Snippets of document content for a given match.
      *
      * <p>Class Example 1:
      * A document contains following text in property subject:
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
index c871905..15acf10 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
@@ -16,16 +16,23 @@
 
 package android.app.appsearch;
 
+import android.annotation.SuppressLint;
 import android.os.Bundle;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 
+import android.app.appsearch.exceptions.AppSearchException;
 import android.app.appsearch.exceptions.IllegalSearchSpecException;
 import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * This class represents the specification logic for AppSearch. It can be used to set the type of
@@ -34,69 +41,26 @@
  */
 // TODO(sidchhabra) : AddResultSpec fields for Snippets etc.
 public final class SearchSpec {
-    /** @hide */
-    
-    public static final String TERM_MATCH_TYPE_FIELD = "termMatchType";
-
-    /** @hide */
-    
-    public static final String SCHEMA_TYPES_FIELD = "schemaType";
-
-    /** @hide */
-    
-    public static final String NAMESPACE_FIELD = "namespace";
-
-    /** @hide */
-    
-    public static final String NUM_PER_PAGE_FIELD = "numPerPage";
-
-    /** @hide */
-    
-    public static final String RANKING_STRATEGY_FIELD = "rankingStrategy";
-
-    /** @hide */
-    
-    public static final String ORDER_FIELD = "order";
-
-    /** @hide */
-    
-    public static final String SNIPPET_COUNT_FIELD = "snippetCount";
-
-    /** @hide */
-    
-    public static final String SNIPPET_COUNT_PER_PROPERTY_FIELD = "snippetCountPerProperty";
-
-    /** @hide */
-    
-    public static final String MAX_SNIPPET_FIELD = "maxSnippet";
+    static final String TERM_MATCH_TYPE_FIELD = "termMatchType";
+    static final String SCHEMA_TYPE_FIELD = "schemaType";
+    static final String NAMESPACE_FIELD = "namespace";
+    static final String NUM_PER_PAGE_FIELD = "numPerPage";
+    static final String RANKING_STRATEGY_FIELD = "rankingStrategy";
+    static final String ORDER_FIELD = "order";
+    static final String SNIPPET_COUNT_FIELD = "snippetCount";
+    static final String SNIPPET_COUNT_PER_PROPERTY_FIELD = "snippetCountPerProperty";
+    static final String MAX_SNIPPET_FIELD = "maxSnippet";
 
     /** @hide */
     
     public static final int DEFAULT_NUM_PER_PAGE = 10;
 
+    // TODO(b/170371356): In framework, we may want these limits might be flag controlled.
     private static final int MAX_NUM_PER_PAGE = 10_000;
     private static final int MAX_SNIPPET_COUNT = 10_000;
     private static final int MAX_SNIPPET_PER_PROPERTY_COUNT = 10_000;
     private static final int MAX_SNIPPET_SIZE_LIMIT = 10_000;
 
-    private final Bundle mBundle;
-
-    /** @hide */
-    
-    public SearchSpec(@NonNull Bundle bundle) {
-        Preconditions.checkNotNull(bundle);
-        mBundle = bundle;
-    }
-
-    /**
-     * Returns the {@link Bundle} populated by this builder.
-     * @hide
-     */
-    @NonNull
-    public Bundle getBundle() {
-        return mBundle;
-    }
-
     /**
      * Term Match Type for the query.
      * @hide
@@ -108,7 +72,7 @@
             TERM_MATCH_PREFIX
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface TermMatchCode {}
+    public @interface TermMatch {}
 
     /**
      * Query terms will only match exact tokens in the index.
@@ -126,14 +90,14 @@
      * @hide
      */
     // NOTE: The integer values of these constants must match the proto enum constants in
-    // {@link ScoringSpecProto.RankingStrategy.Code }
+    // {@link ScoringSpecProto.RankingStrategy.Code}
     @IntDef(value = {
             RANKING_STRATEGY_NONE,
             RANKING_STRATEGY_DOCUMENT_SCORE,
             RANKING_STRATEGY_CREATION_TIMESTAMP
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface RankingStrategyCode {}
+    public @interface RankingStrategy {}
 
     /** No Ranking, results are returned in arbitrary order.*/
     public static final int RANKING_STRATEGY_NONE = 0;
@@ -147,23 +111,109 @@
      * @hide
      */
     // NOTE: The integer values of these constants must match the proto enum constants in
-    // {@link ScoringSpecProto.Order.Code }
+    // {@link ScoringSpecProto.Order.Code}
     @IntDef(value = {
             ORDER_DESCENDING,
             ORDER_ASCENDING
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface OrderCode {}
+    public @interface Order {}
 
     /** Search results will be returned in a descending order. */
     public static final int ORDER_DESCENDING = 0;
     /** Search results will be returned in an ascending order. */
     public static final int ORDER_ASCENDING = 1;
 
+    private final Bundle mBundle;
+
+    /** @hide */
+    
+    public SearchSpec(@NonNull Bundle bundle) {
+        Preconditions.checkNotNull(bundle);
+        mBundle = bundle;
+    }
+
+    /**
+     * Returns the {@link Bundle} populated by this builder.
+     * @hide
+     */
+    
+    @NonNull
+    public Bundle getBundle() {
+        return mBundle;
+    }
+
+    /** Returns how the query terms should match terms in the index. */
+    public @TermMatch int getTermMatch() {
+        return mBundle.getInt(TERM_MATCH_TYPE_FIELD, -1);
+    }
+
+    /**
+     * Returns the list of schema types to search for.
+     *
+     * <p>If empty, the query will search over all schema types.
+     */
+    @NonNull
+    public List<String> getSchemas() {
+        List<String> schemas = mBundle.getStringArrayList(SCHEMA_TYPE_FIELD);
+        if (schemas == null) {
+            return Collections.emptyList();
+        }
+        return Collections.unmodifiableList(schemas);
+    }
+
+    /**
+     * Returns the list of namespaces to search for.
+     *
+     * <p>If empty, the query will search over all namespaces.
+     */
+    @NonNull
+    public List<String> getNamespaces() {
+        List<String> namespaces = mBundle.getStringArrayList(NAMESPACE_FIELD);
+        if (namespaces == null) {
+            return Collections.emptyList();
+        }
+        return Collections.unmodifiableList(namespaces);
+    }
+
+    /** Returns the number of results per page in the returned object. */
+    public int getNumPerPage() {
+        return mBundle.getInt(NUM_PER_PAGE_FIELD, DEFAULT_NUM_PER_PAGE);
+    }
+
+    /** Returns the ranking strategy. */
+    public @RankingStrategy int getRankingStrategy() {
+        return mBundle.getInt(RANKING_STRATEGY_FIELD);
+    }
+
+    /** Returns the order of returned search results (descending or ascending). */
+    public @Order int getOrder() {
+        return mBundle.getInt(ORDER_FIELD);
+    }
+
+    /** Returns how many documents to generate snippets for. */
+    public int getSnippetCount() {
+        return mBundle.getInt(SNIPPET_COUNT_FIELD);
+    }
+
+    /**
+     * Returns how many matches for each property of a matching document to generate snippets for.
+     */
+    public int getSnippetCountPerProperty() {
+        return mBundle.getInt(SNIPPET_COUNT_PER_PROPERTY_FIELD);
+    }
+
+    /** Returns the maximum size of a snippet in characters. */
+    public int getMaxSnippetSize() {
+        return mBundle.getInt(MAX_SNIPPET_FIELD);
+    }
+
     /** Builder for {@link SearchSpec objects}. */
     public static final class Builder {
 
         private final Bundle mBundle;
+        private final ArrayList<String> mSchemaTypes = new ArrayList<>();
+        private final ArrayList<String> mNamespaces = new ArrayList<>();
         private boolean mBuilt = false;
 
         /** Creates a new {@link SearchSpec.Builder}. */
@@ -176,7 +226,7 @@
          * Indicates how the query terms should match {@code TermMatchCode} in the index.
          */
         @NonNull
-        public Builder setTermMatch(@TermMatchCode int termMatchTypeCode) {
+        public Builder setTermMatch(@TermMatch int termMatchTypeCode) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkArgumentInRange(termMatchTypeCode, TERM_MATCH_EXACT_ONLY,
                     TERM_MATCH_PREFIX, "Term match type");
@@ -187,13 +237,27 @@
         /**
          * Adds a Schema type filter to {@link SearchSpec} Entry. Only search for documents that
          * have the specified schema types.
+         *
          * <p>If unset, the query will search over all schema types.
          */
         @NonNull
-        public Builder setSchemaTypes(@NonNull String... schemaTypes) {
+        public Builder addSchema(@NonNull String... schemaTypes) {
             Preconditions.checkNotNull(schemaTypes);
             Preconditions.checkState(!mBuilt, "Builder has already been used");
-            mBundle.putStringArray(SCHEMA_TYPES_FIELD, schemaTypes);
+            return addSchema(Arrays.asList(schemaTypes));
+        }
+
+        /**
+         * Adds a Schema type filter to {@link SearchSpec} Entry. Only search for documents that
+         * have the specified schema types.
+         *
+         * <p>If unset, the query will search over all schema types.
+         */
+        @NonNull
+        public Builder addSchema(@NonNull Collection<String> schemaTypes) {
+            Preconditions.checkNotNull(schemaTypes);
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mSchemaTypes.addAll(schemaTypes);
             return this;
         }
 
@@ -203,10 +267,22 @@
          * <p>If unset, the query will search over all namespaces.
          */
         @NonNull
-        public Builder setNamespaces(@NonNull String... namespaces) {
+        public Builder addNamespace(@NonNull String... namespaces) {
             Preconditions.checkNotNull(namespaces);
             Preconditions.checkState(!mBuilt, "Builder has already been used");
-            mBundle.putStringArray(NAMESPACE_FIELD, namespaces);
+            return addNamespace(Arrays.asList(namespaces));
+        }
+
+        /**
+         * Adds a namespace filter to {@link SearchSpec} Entry. Only search for documents that
+         * have the specified namespaces.
+         * <p>If unset, the query will search over all namespaces.
+         */
+        @NonNull
+        public Builder addNamespace(@NonNull Collection<String> namespaces) {
+            Preconditions.checkNotNull(namespaces);
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+            mNamespaces.addAll(namespaces);
             return this;
         }
 
@@ -224,7 +300,7 @@
 
         /** Sets ranking strategy for AppSearch results.*/
         @NonNull
-        public Builder setRankingStrategy(@RankingStrategyCode int rankingStrategy) {
+        public Builder setRankingStrategy(@RankingStrategy int rankingStrategy) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkArgumentInRange(rankingStrategy, RANKING_STRATEGY_NONE,
                     RANKING_STRATEGY_CREATION_TIMESTAMP, "Result ranking strategy");
@@ -238,7 +314,7 @@
          * <p>This order field will be ignored if RankingStrategy = {@code RANKING_STRATEGY_NONE}.
          */
         @NonNull
-        public Builder setOrder(@OrderCode int order) {
+        public Builder setOrder(@Order int order) {
             Preconditions.checkState(!mBuilt, "Builder has already been used");
             Preconditions.checkArgumentInRange(order, ORDER_DESCENDING, ORDER_ASCENDING,
                     "Result ranking order");
@@ -264,11 +340,12 @@
         }
 
         /**
-         * Only the first {@code matchesCountPerProperty} matches for a every property of
-         * {@link GenericDocument} will contain snippet information.
+         * Sets {@code snippetCountPerProperty}. Only the first {@code snippetCountPerProperty}
+         * snippets for a every property of {@link GenericDocument} will contain snippet
+         * information.
          *
-         * <p>If set to 0, snippeting is disabled and {@link SearchResult#getMatches} will return
-         * {@code null} for that result.
+         * <p>If set to 0, snippeting is disabled and {@link SearchResult#getMatches}
+         * will return {@code null} for that result.
          *
          * <p>The value should be set in range[0, 10k].
          */
@@ -286,10 +363,13 @@
          * {@code maxSnippetSize/2} bytes before the middle of the matching token and end at
          * {@code maxSnippetSize/2} bytes after the middle of the matching token. It respects
          * token boundaries, therefore the returned window may be smaller than requested.
+         *
          * <p> Setting {@code maxSnippetSize} to 0 will disable windowing and an empty string will
          * be returned. If matches enabled is also set to false, then snippeting is disabled.
+         *
          * <p>Ex. {@code maxSnippetSize} = 16. "foo bar baz bat rat" with a query of "baz" will
          * return a window of "bar baz bat" which is only 11 bytes long.
+         *
          * <p>The value should be in range[0, 10k].
          */
         @NonNull
@@ -312,6 +392,8 @@
             if (!mBundle.containsKey(TERM_MATCH_TYPE_FIELD)) {
                 throw new IllegalSearchSpecException("Missing termMatchType field.");
             }
+            mBundle.putStringArrayList(NAMESPACE_FIELD, mNamespaces);
+            mBundle.putStringArrayList(SCHEMA_TYPE_FIELD, mSchemaTypes);
             mBuilt = true;
             return new SearchSpec(mBundle);
         }
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
index b2e9d46..f2c8156 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
@@ -16,13 +16,17 @@
 
 package android.app.appsearch;
 
-import android.annotation.NonNull;
-import android.util.ArraySet;
+import android.annotation.SuppressLint;
 
+import android.annotation.NonNull;
+import android.app.appsearch.exceptions.AppSearchException;
+import android.util.ArraySet;
 import com.android.internal.util.Preconditions;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -40,15 +44,13 @@
         mForceOverride = forceOverride;
     }
 
-    /** @hide */
-    
+    /** Returns the schemas that are part of this request. */
     @NonNull
     public Set<AppSearchSchema> getSchemas() {
         return mSchemas;
     }
 
-    /** @hide */
-    
+    /** Returns whether this request will force the schema to be overridden. */
     public boolean isForceOverride() {
         return mForceOverride;
     }
diff --git a/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java b/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java
index d490469..15d0992 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java
@@ -54,6 +54,7 @@
         mResultCode = resultCode;
     }
 
+    /** Returns the result code this exception was constructed with. */
     public @AppSearchResult.ResultCode int getResultCode() {
         return mResultCode;
     }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 7cd6ee2..f2830e5 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -33,11 +33,11 @@
 import com.android.internal.infra.AndroidFuture;
 import com.android.internal.util.Preconditions;
 import com.android.server.SystemService;
-import com.android.server.appsearch.external.localbackend.AppSearchImpl;
-import com.android.server.appsearch.external.localbackend.converter.GenericDocumentToProtoConverter;
-import com.android.server.appsearch.external.localbackend.converter.SchemaToProtoConverter;
-import com.android.server.appsearch.external.localbackend.converter.SearchResultToProtoConverter;
-import com.android.server.appsearch.external.localbackend.converter.SearchSpecToProtoConverter;
+import com.android.server.appsearch.external.localstorage.AppSearchImpl;
+import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
+import com.android.server.appsearch.external.localstorage.converter.SchemaToProtoConverter;
+import com.android.server.appsearch.external.localstorage.converter.SearchResultToProtoConverter;
+import com.android.server.appsearch.external.localstorage.converter.SearchSpecToProtoConverter;
 
 import com.google.android.icing.proto.DocumentProto;
 import com.google.android.icing.proto.SchemaProto;
@@ -46,6 +46,7 @@
 import com.google.android.icing.proto.SearchSpecProto;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -193,7 +194,12 @@
                         SearchSpecToProtoConverter.toResultSpecProto(searchSpec),
                         SearchSpecToProtoConverter.toScoringSpecProto(searchSpec));
                 List<SearchResult> searchResultList =
-                        SearchResultToProtoConverter.convert(searchResultProto);
+                        new ArrayList<>(searchResultProto.getResultsCount());
+                for (int i = 0; i < searchResultProto.getResultsCount(); i++) {
+                    SearchResult result = SearchResultToProtoConverter.convertSearchResult(
+                            searchResultProto.getResults(i));
+                    searchResultList.add(result);
+                }
                 SearchResults searchResults =
                         new SearchResults(searchResultList, searchResultProto.getNextPageToken());
                 callback.complete(AppSearchResult.newSuccessfulResult(searchResults));
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
index 60f7005..2871eb6 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
@@ -24,7 +24,7 @@
 import android.os.storage.StorageManager;
 import android.util.SparseArray;
 
-import com.android.server.appsearch.external.localbackend.AppSearchImpl;
+import com.android.server.appsearch.external.localstorage.AppSearchImpl;
 
 import java.io.File;
 
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
similarity index 99%
rename from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/AppSearchImpl.java
rename to apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index 642378d..b1a79f8 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.appsearch.external.localbackend;
+package com.android.server.appsearch.external.localstorage;
 
 import android.util.Log;
 
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
similarity index 69%
rename from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverter.java
rename to apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
index fdeb90d..60684f0 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.appsearch.external.localbackend.converter;
-
-import android.os.Bundle;
+package com.android.server.appsearch.external.localstorage.converter;
 
 import android.annotation.NonNull;
 
@@ -43,7 +41,6 @@
     @SuppressWarnings("unchecked")
     public static DocumentProto convert(@NonNull GenericDocument document) {
         Preconditions.checkNotNull(document);
-        Bundle properties = document.getBundle().getBundle(GenericDocument.PROPERTIES_FIELD);
         DocumentProto.Builder mProtoBuilder = DocumentProto.newBuilder();
         mProtoBuilder.setUri(document.getUri())
                 .setSchema(document.getSchemaType())
@@ -51,42 +48,45 @@
                 .setScore(document.getScore())
                 .setTtlMs(document.getTtlMillis())
                 .setCreationTimestampMs(document.getCreationTimestampMillis());
-        ArrayList<String> keys = new ArrayList<>(properties.keySet());
+        ArrayList<String> keys = new ArrayList<>(document.getPropertyNames());
         Collections.sort(keys);
         for (int i = 0; i < keys.size(); i++) {
             String name = keys.get(i);
-            Object values = properties.get(name);
             PropertyProto.Builder propertyProto = PropertyProto.newBuilder().setName(name);
-            if (values instanceof boolean[]) {
-                for (boolean value : (boolean[]) values) {
-                    propertyProto.addBooleanValues(value);
+            String[] stringValues = document.getPropertyStringArray(name);
+            long[] longValues = document.getPropertyLongArray(name);
+            double[] doubleValues = document.getPropertyDoubleArray(name);
+            boolean[] booleanValues = document.getPropertyBooleanArray(name);
+            byte[][] bytesValues = document.getPropertyBytesArray(name);
+            GenericDocument[] documentValues = document.getPropertyDocumentArray(name);
+            if (stringValues != null) {
+                for (int j = 0; j < stringValues.length; j++) {
+                    propertyProto.addStringValues(stringValues[j]);
                 }
-            } else if (values instanceof long[]) {
-                for (long value : (long[]) values) {
-                    propertyProto.addInt64Values(value);
+            } else if (longValues != null) {
+                for (int j = 0; j < longValues.length; j++) {
+                    propertyProto.addInt64Values(longValues[j]);
                 }
-            } else if (values instanceof double[]) {
-                for (double value : (double[]) values) {
-                    propertyProto.addDoubleValues(value);
+            } else if (doubleValues != null) {
+                for (int j = 0; j < doubleValues.length; j++) {
+                    propertyProto.addDoubleValues(doubleValues[j]);
                 }
-            } else if (values instanceof String[]) {
-                for (String value : (String[]) values) {
-                    propertyProto.addStringValues(value);
+            } else if (booleanValues != null) {
+                for (int j = 0; j < booleanValues.length; j++) {
+                    propertyProto.addBooleanValues(booleanValues[j]);
                 }
-            } else if (values instanceof ArrayList) {
-                for (Bundle bundle : (ArrayList<Bundle>) values) {
-                    byte[] value = bundle.getByteArray(GenericDocument.BYTE_ARRAY_FIELD);
-                    propertyProto.addBytesValues(ByteString.copyFrom(value));
+            } else if (bytesValues != null) {
+                for (int j = 0; j < bytesValues.length; j++) {
+                    propertyProto.addBytesValues(ByteString.copyFrom(bytesValues[j]));
                 }
-            } else if (values instanceof Bundle[]) {
-                for (Bundle bundle : (Bundle[]) values) {
-                    GenericDocument value = new GenericDocument(bundle);
-                    propertyProto.addDocumentValues(convert(value));
+            } else if (documentValues != null) {
+                for (int j = 0; j < documentValues.length; j++) {
+                    DocumentProto proto = convert(documentValues[j]);
+                    propertyProto.addDocumentValues(proto);
                 }
             } else {
                 throw new IllegalStateException(
-                        "Property \"" + name + "\" has unsupported value type \""
-                                + values.getClass().getSimpleName() + "\"");
+                        "Property \"" + name + "\" has unsupported value type");
             }
             mProtoBuilder.addProperties(propertyProto);
         }
@@ -107,42 +107,42 @@
         for (int i = 0; i < proto.getPropertiesCount(); i++) {
             PropertyProto property = proto.getProperties(i);
             String name = property.getName();
-            if (property.getBooleanValuesCount() > 0) {
-                boolean[] values = new boolean[property.getBooleanValuesCount()];
+            if (property.getStringValuesCount() > 0) {
+                String[] values = new String[property.getStringValuesCount()];
                 for (int j = 0; j < values.length; j++) {
-                    values[j] = property.getBooleanValues(j);
+                    values[j] = property.getStringValues(j);
                 }
-                documentBuilder.setProperty(name, values);
+                documentBuilder.setPropertyString(name, values);
             } else if (property.getInt64ValuesCount() > 0) {
                 long[] values = new long[property.getInt64ValuesCount()];
                 for (int j = 0; j < values.length; j++) {
                     values[j] = property.getInt64Values(j);
                 }
-                documentBuilder.setProperty(name, values);
+                documentBuilder.setPropertyLong(name, values);
             } else if (property.getDoubleValuesCount() > 0) {
                 double[] values = new double[property.getDoubleValuesCount()];
                 for (int j = 0; j < values.length; j++) {
                     values[j] = property.getDoubleValues(j);
                 }
-                documentBuilder.setProperty(name, values);
-            } else if (property.getStringValuesCount() > 0) {
-                String[] values = new String[property.getStringValuesCount()];
+                documentBuilder.setPropertyDouble(name, values);
+            } else if (property.getBooleanValuesCount() > 0) {
+                boolean[] values = new boolean[property.getBooleanValuesCount()];
                 for (int j = 0; j < values.length; j++) {
-                    values[j] = property.getStringValues(j);
+                    values[j] = property.getBooleanValues(j);
                 }
-                documentBuilder.setProperty(name, values);
+                documentBuilder.setPropertyBoolean(name, values);
             } else if (property.getBytesValuesCount() > 0) {
                 byte[][] values = new byte[property.getBytesValuesCount()][];
                 for (int j = 0; j < values.length; j++) {
                     values[j] = property.getBytesValues(j).toByteArray();
                 }
-                documentBuilder.setProperty(name, values);
+                documentBuilder.setPropertyBytes(name, values);
             } else if (property.getDocumentValuesCount() > 0) {
                 GenericDocument[] values = new GenericDocument[property.getDocumentValuesCount()];
                 for (int j = 0; j < values.length; j++) {
                     values[j] = convert(property.getDocumentValues(j));
                 }
-                documentBuilder.setProperty(name, values);
+                documentBuilder.setPropertyDocument(name, values);
             } else {
                 throw new IllegalStateException("Unknown type of value: " + name);
             }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
similarity index 73%
rename from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverter.java
rename to apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
index ca0d2ee..403711f 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.appsearch.external.localbackend.converter;
-
-import android.os.Bundle;
+package com.android.server.appsearch.external.localstorage.converter;
 
 import android.annotation.NonNull;
 
@@ -28,7 +26,7 @@
 import com.google.android.icing.proto.SchemaTypeConfigProto;
 import com.google.android.icing.proto.TermMatchType;
 
-import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Translates an {@link AppSearchSchema} into a {@link SchemaTypeConfigProto}.
@@ -45,31 +43,26 @@
     @NonNull
     public static SchemaTypeConfigProto convert(@NonNull AppSearchSchema schema) {
         Preconditions.checkNotNull(schema);
-        Bundle bundle = schema.getBundle();
         SchemaTypeConfigProto.Builder protoBuilder =
-                SchemaTypeConfigProto.newBuilder()
-                        .setSchemaType(bundle.getString(AppSearchSchema.SCHEMA_TYPE_FIELD, ""));
-        ArrayList<Bundle> properties =
-                bundle.getParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD);
-        if (properties != null) {
-            for (int i = 0; i < properties.size(); i++) {
-                PropertyConfigProto propertyProto = convertProperty(properties.get(i));
-                protoBuilder.addProperties(propertyProto);
-            }
+                SchemaTypeConfigProto.newBuilder().setSchemaType(schema.getSchemaTypeName());
+        List<AppSearchSchema.PropertyConfig> properties = schema.getProperties();
+        for (int i = 0; i < properties.size(); i++) {
+            PropertyConfigProto propertyProto = convertProperty(properties.get(i));
+            protoBuilder.addProperties(propertyProto);
         }
         return protoBuilder.build();
     }
 
     @NonNull
-    private static PropertyConfigProto convertProperty(@NonNull Bundle bundle) {
-        Preconditions.checkNotNull(bundle);
+    private static PropertyConfigProto convertProperty(
+            @NonNull AppSearchSchema.PropertyConfig property) {
+        Preconditions.checkNotNull(property);
         PropertyConfigProto.Builder propertyConfigProto = PropertyConfigProto.newBuilder()
-                .setPropertyName(bundle.getString(AppSearchSchema.PropertyConfig.NAME_FIELD, ""));
+                .setPropertyName(property.getName());
         IndexingConfig.Builder indexingConfig = IndexingConfig.newBuilder();
 
         // Set dataType
-        @AppSearchSchema.PropertyConfig.DataType int dataType =
-                bundle.getInt(AppSearchSchema.PropertyConfig.DATA_TYPE_FIELD);
+        @AppSearchSchema.PropertyConfig.DataType int dataType = property.getDataType();
         PropertyConfigProto.DataType.Code dataTypeProto =
                 PropertyConfigProto.DataType.Code.forNumber(dataType);
         if (dataTypeProto == null) {
@@ -78,12 +71,13 @@
         propertyConfigProto.setDataType(dataTypeProto);
 
         // Set schemaType
-        propertyConfigProto.setSchemaType(
-                bundle.getString(AppSearchSchema.PropertyConfig.SCHEMA_TYPE_FIELD, ""));
+        String schemaType = property.getSchemaType();
+        if (schemaType != null) {
+            propertyConfigProto.setSchemaType(schemaType);
+        }
 
         // Set cardinality
-        @AppSearchSchema.PropertyConfig.Cardinality int cardinality =
-                bundle.getInt(AppSearchSchema.PropertyConfig.CARDINALITY_FIELD);
+        @AppSearchSchema.PropertyConfig.Cardinality int cardinality = property.getCardinality();
         PropertyConfigProto.Cardinality.Code cardinalityProto =
                 PropertyConfigProto.Cardinality.Code.forNumber(cardinality);
         if (cardinalityProto == null) {
@@ -92,8 +86,7 @@
         propertyConfigProto.setCardinality(cardinalityProto);
 
         // Set indexingType
-        @AppSearchSchema.PropertyConfig.IndexingType int indexingType =
-                bundle.getInt(AppSearchSchema.PropertyConfig.INDEXING_TYPE_FIELD);
+        @AppSearchSchema.PropertyConfig.IndexingType int indexingType = property.getIndexingType();
         TermMatchType.Code termMatchTypeProto;
         switch (indexingType) {
             case AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE:
@@ -112,7 +105,7 @@
 
         // Set tokenizerType
         @AppSearchSchema.PropertyConfig.TokenizerType int tokenizerType =
-                bundle.getInt(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_FIELD);
+                property.getTokenizerType();
         IndexingConfig.TokenizerType.Code tokenizerTypeProto =
                 IndexingConfig.TokenizerType.Code.forNumber(tokenizerType);
         if (tokenizerTypeProto == null) {
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchResultToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
similarity index 79%
rename from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchResultToProtoConverter.java
rename to apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
index 524c80d..9f7c696 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchResultToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.appsearch.external.localbackend.converter;
+package com.android.server.appsearch.external.localstorage.converter;
 
 import android.os.Bundle;
 
@@ -22,43 +22,32 @@
 
 import android.app.appsearch.GenericDocument;
 import android.app.appsearch.SearchResult;
-import android.app.appsearch.SearchResults;
 
 import com.google.android.icing.proto.SearchResultProto;
 import com.google.android.icing.proto.SnippetMatchProto;
 import com.google.android.icing.proto.SnippetProto;
 
 import java.util.ArrayList;
-import java.util.List;
 
 /**
- * Translates a {@link SearchResultProto} into {@link SearchResults}.
+ * Translates a {@link SearchResultProto} into {@link SearchResult}s.
+ *
  * @hide
  */
 
 public class SearchResultToProtoConverter {
     private SearchResultToProtoConverter() {}
 
-    /** Translates a {@link SearchResultProto} into a list of {@link SearchResult}. */
-    @NonNull
-    public static List<SearchResult> convert(@NonNull SearchResultProto searchResultProto) {
-        List<SearchResult> results = new ArrayList<>(searchResultProto.getResultsCount());
-        for (int i = 0; i < searchResultProto.getResultsCount(); i++) {
-            results.add(convertSearchResult(searchResultProto.getResults(i)));
-        }
-        return results;
-    }
-
     /** Translate a {@link SearchResultProto.ResultProto} into {@link SearchResult}. */
     @NonNull
-    static SearchResult convertSearchResult(@NonNull SearchResultProto.ResultProto proto) {
+    public static SearchResult convertSearchResult(
+            @NonNull SearchResultProto.ResultProtoOrBuilder proto) {
         Bundle bundle = new Bundle();
         GenericDocument document = GenericDocumentToProtoConverter.convert(proto.getDocument());
         bundle.putBundle(SearchResult.DOCUMENT_FIELD, document.getBundle());
 
-        ArrayList<Bundle> matchList = null;
+        ArrayList<Bundle> matchList = new ArrayList<>();
         if (proto.hasSnippet()) {
-            matchList = new ArrayList<>();
             for (int i = 0; i < proto.getSnippet().getEntriesCount(); i++) {
                 SnippetProto.EntryProto entry = proto.getSnippet().getEntries(i);
                 for (int j = 0; j < entry.getSnippetMatchesCount(); j++) {
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchSpecToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java
similarity index 67%
rename from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchSpecToProtoConverter.java
rename to apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java
index a5d913a..14822dc 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchSpecToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.appsearch.external.localbackend.converter;
-
-import android.os.Bundle;
+package com.android.server.appsearch.external.localstorage.converter;
 
 import android.annotation.NonNull;
 
@@ -28,8 +26,6 @@
 import com.google.android.icing.proto.SearchSpecProto;
 import com.google.android.icing.proto.TermMatchType;
 
-import java.util.Arrays;
-
 /**
  * Translates a {@link SearchSpec} into icing search protos.
  * @hide
@@ -42,25 +38,17 @@
     @NonNull
     public static SearchSpecProto toSearchSpecProto(@NonNull SearchSpec spec) {
         Preconditions.checkNotNull(spec);
-        Bundle bundle = spec.getBundle();
-        SearchSpecProto.Builder protoBuilder = SearchSpecProto.newBuilder();
+        SearchSpecProto.Builder protoBuilder = SearchSpecProto.newBuilder()
+                .addAllSchemaTypeFilters(spec.getSchemas())
+                .addAllNamespaceFilters(spec.getNamespaces());
 
-        @SearchSpec.TermMatchCode int termMatchCode =
-                bundle.getInt(SearchSpec.TERM_MATCH_TYPE_FIELD);
+        @SearchSpec.TermMatch int termMatchCode = spec.getTermMatch();
         TermMatchType.Code termMatchCodeProto = TermMatchType.Code.forNumber(termMatchCode);
         if (termMatchCodeProto == null || termMatchCodeProto.equals(TermMatchType.Code.UNKNOWN)) {
             throw new IllegalArgumentException("Invalid term match type: " + termMatchCode);
         }
         protoBuilder.setTermMatchType(termMatchCodeProto);
 
-        String[] schemaTypes = bundle.getStringArray(SearchSpec.SCHEMA_TYPES_FIELD);
-        if (schemaTypes != null) {
-            protoBuilder.addAllSchemaTypeFilters(Arrays.asList(schemaTypes));
-        }
-        String[] namespaces = bundle.getStringArray(SearchSpec.NAMESPACE_FIELD);
-        if (namespaces != null) {
-            protoBuilder.addAllNamespaceFilters(Arrays.asList(namespaces));
-        }
         return protoBuilder.build();
     }
 
@@ -68,27 +56,23 @@
     @NonNull
     public static ResultSpecProto toResultSpecProto(@NonNull SearchSpec spec) {
         Preconditions.checkNotNull(spec);
-        Bundle bundle = spec.getBundle();
         return ResultSpecProto.newBuilder()
-                .setNumPerPage(bundle.getInt(
-                        SearchSpec.NUM_PER_PAGE_FIELD, SearchSpec.DEFAULT_NUM_PER_PAGE))
-                .setSnippetSpec(ResultSpecProto.SnippetSpecProto.newBuilder()
-                        .setNumToSnippet(bundle.getInt(SearchSpec.SNIPPET_COUNT_FIELD))
-                        .setNumMatchesPerProperty(
-                                bundle.getInt(SearchSpec.SNIPPET_COUNT_PER_PROPERTY_FIELD))
-                        .setMaxWindowBytes(bundle.getInt(SearchSpec.MAX_SNIPPET_FIELD)))
+                .setNumPerPage(spec.getNumPerPage())
+                .setSnippetSpec(
+                        ResultSpecProto.SnippetSpecProto.newBuilder()
+                                .setNumToSnippet(spec.getSnippetCount())
+                                .setNumMatchesPerProperty(spec.getSnippetCountPerProperty())
+                                .setMaxWindowBytes(spec.getMaxSnippetSize()))
                 .build();
-
     }
 
     /** Extracts {@link ScoringSpecProto} information from a {@link SearchSpec}. */
     @NonNull
     public static ScoringSpecProto toScoringSpecProto(@NonNull SearchSpec spec) {
         Preconditions.checkNotNull(spec);
-        Bundle bundle = spec.getBundle();
         ScoringSpecProto.Builder protoBuilder = ScoringSpecProto.newBuilder();
 
-        @SearchSpec.OrderCode int orderCode = bundle.getInt(SearchSpec.ORDER_FIELD);
+        @SearchSpec.Order int orderCode = spec.getOrder();
         ScoringSpecProto.Order.Code orderCodeProto =
                 ScoringSpecProto.Order.Code.forNumber(orderCode);
         if (orderCodeProto == null) {
@@ -96,8 +80,7 @@
         }
         protoBuilder.setOrderBy(orderCodeProto);
 
-        @SearchSpec.RankingStrategyCode int rankingStrategyCode =
-                bundle.getInt(SearchSpec.RANKING_STRATEGY_FIELD);
+        @SearchSpec.RankingStrategy int rankingStrategyCode = spec.getRankingStrategy();
         ScoringSpecProto.RankingStrategy.Code rankingStrategyCodeProto =
                 ScoringSpecProto.RankingStrategy.Code.forNumber(rankingStrategyCode);
         if (rankingStrategyCodeProto == null) {
diff --git a/apex/extservices/Android.bp b/apex/extservices/Android.bp
deleted file mode 100644
index 0c6c4c2..0000000
--- a/apex/extservices/Android.bp
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (C) 2020 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.
-
-apex {
-    name: "com.android.extservices",
-    defaults: ["com.android.extservices-defaults"],
-    manifest: "apex_manifest.json",
-}
-
-apex_defaults {
-    name: "com.android.extservices-defaults",
-    updatable: true,
-    min_sdk_version: "current",
-    key: "com.android.extservices.key",
-    certificate: ":com.android.extservices.certificate",
-    apps: ["ExtServices"],
-}
-
-apex_key {
-    name: "com.android.extservices.key",
-    public_key: "com.android.extservices.avbpubkey",
-    private_key: "com.android.extservices.pem",
-}
-
-android_app_certificate {
-    name: "com.android.extservices.certificate",
-    certificate: "com.android.extservices",
-}
diff --git a/apex/extservices/apex_manifest.json b/apex/extservices/apex_manifest.json
deleted file mode 100644
index b4acf128..0000000
--- a/apex/extservices/apex_manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "com.android.extservices",
-  "version": 300000000
-}
diff --git a/apex/extservices/com.android.extservices.avbpubkey b/apex/extservices/com.android.extservices.avbpubkey
deleted file mode 100644
index f37d3e4..0000000
--- a/apex/extservices/com.android.extservices.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/apex/extservices/com.android.extservices.pem b/apex/extservices/com.android.extservices.pem
deleted file mode 100644
index 7bfbd34..0000000
--- a/apex/extservices/com.android.extservices.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKAIBAAKCAgEAuYshVDiRkt3tmBhqcWkKOm5GcviKpLbHSPpYQDHGDwS0dqqL
-SqAd1/BgT/bVVtUkAciFApPnXn96WhNYCypptyC5FHCxM21uBCGmow+3WermD++w
-5dQk4QP2ONPIpG+KzOWBl9SiBud4SpOHDyr0JycBsrXS89Tln9kAsTDuDEFfXL/J
-8cX/S3IUwhPV0pAlgUIHdDp0DGFjZaJlEZBZ+HmImriC/AUNUMVb5lfbczXOEZPF
-0A9+JzYschfXUxn8nu1N7RN5GDbq+chszx1FMVhuFUheukkd4dLNSDl0O0RlUnD+
-C/xz1ilDzEVZhnMtMnxS9oJ8bA/HUVMfsFnaQbgGmQ0CcxFxnfbYyGXGG1H+b8vA
-MTVQi5rZXG2p+VgHIAKVrYmpETVnRPgoMqp18KuGtp5SDngi13G3YEzS7iFbqfYh
-6iW2G974nD/Dq0cSire8Oljd9PEaMCMZiP5PTFJp0G/mtw7ROoyZqsSM6rX3XVTo
-Y5dBmBMctSJ8rgDMi0ZNvRH+rq/E5+RT6yMAJ7DDbOJzBnQ3IIoGn8NzUT3P1FCB
-HYEp1U2N7QNirIQMAuVz3IlHae9N1kl3eGAO6f2CjV7vZmFpDeWw+KSYs71mRkOb
-WBgl6D9FFq4u1azrU3AwV0dj3x1eU6yVnKUy1J7ppF/mcR+VzH7ThzTdV7cCAwEA
-AQKCAgEApWFU2Mv/PYhg0bPZlLLKsiA+3RWaBo0AfpTd+oIjBpnr/OWweFjVoPcZ
-8cyShe4/RPOlUxHgJcO8m/MoA/PO/LLHJWf5GlzMthQEgs1sYVJVtBiydXitUn+E
-hUyIR8FAV7et1lZqAXtqJhbvSF7B9u/2vIMCv+GgtuTmkAmL9RKD3Jj6eG1CS84o
-oICrkx52v4rKOBgt/icEQMAKFCi1eRti3n3eCqK6JqdzbZIcAcoQnmw34mccy/im
-jx+fBuxf1oywa8NyqVmyAehazBVL6lrm7ENwY9zuLK4H2fuUFYu2QFCEsMxZt6da
-TgX2cTfSLnDQRfcyzeMWhu9vjHHabjpLNjiCKhIhGyO0rO1rtea8ajZHgM/2sxXq
-6gLynW0dlatlxmjANlN9WQPGNdzvcIFJ0TLnI4mlJnWpqCsN9iW1d4ey13WiZUVR
-DgtnR60zao+LRCCM4D3cuVLq0DjL2BlHGXnOPK/LpQG1LbI1TroZpgSEHSZlQRzT
-ql9txgNqTHxijXuPL2VhhwhW7cqDoO8sLwV3BqDMIH56U0cbUBiSA/G9fKeI/DEG
-i7LcrMgrBk+xnuAWoFHuzfBMAdD9i3kYyk+41tOmcza2TNJgxadVYp5woHFvYvS/
-GKaNiRz0XmcijO5Ir0yxgCq21BdkWzo5zVrTFABiKeR7YXiee8kCggEBAOeULWgR
-spolJJrACWJspRvKb9FGnbGiYOnCGJoAc751kuXmNxoyWnEwgcjrSEoayNPUfOtz
-IgA+twqjgl0Zec2XFPfUcgWUBrrvvUEV4NIH5ibaR7ezHGeovCWs9XoDyzHHvhDr
-c6T5kXFZ60rS5h6LGUnE1hkHFJoHuTIBbn9j7eIbri8S71i7HWQ04s4KuQ+Bwbxm
-UnkEhbc+zMWHXfXy7rx4/eEZcZwtEybIORcHXYNPGeqMfOlcEMHpKEOi+NvDA6cp
-vTaTSwJ6ZBgYh7Tw3bNgRxSknaIhcGwMD0ojStjC5xzXT1Zr2Z3GXwYvOGcq3MeZ
-z+V2cx5xuwyp7R0CggEBAM0cKKNZEZwi/1zBPUDMFB4iJoX12BxQX6e5wdlHGXgF
-XeZwCnaIxOxMDxH79M5Svmpdu/jkUijI/pRvcE1iohFyIBvTUSDmlAoy4keXqMEQ
-M2hA+TwVA3JLmMcV8HKy/MFlwwKJB1JDcoxGjnXsM5UjVTD2jilO7vlJZs3+0ws0
-R7qzRT3ED25QTpZyDYcKE2otc5bzIZG3yAaJtWd3NugWsKpxDgr2RFUGJiHBq72n
-48FkSjfgaDTn83zYcPvS0Uykb2ho8G/N+EurstL41n3nQo0I7FLbyptOopDDwsSp
-Ndejn08NVAQ+xFAafOyqHkA3Ytpl0QCZDpMBuLdvw+MCggEAOVMt1kgjPRMat4/4
-ArxANtvqyBRB7vnyIYthiaW5ARmbrntJgpuaVdCbIABWGbn9oqpD7gjHDuZ3axPE
-roUi6KiQkTSusQDOlbHI2Haw+2znJRD9ldSpoGNdh7oD3htYTk9Sll+ideEthrCq
-lRAV1NO8A83M7c8Z43Mr/dvq3XAAL+uIN7DpPL687NRGnJh87QDC039ExR5Ad3b9
-O5xhvwNO46rTtcgVnoJt7ji8IR46oMmQ8cWrGh0nLMkppWyPS98/ZT7ozryxYcCo
-TGquFTVWvBOGJO8G8l5ytNxbYI/R9Exy52nJAuyZpvu3BBHmVWt/0Y0asIOcxZmD
-owPhZQKCAQAfWAFBzReq05JQe1s/7q/YVwGqEQKgeQvVFsbvzDSxKajK0S5YJNhq
-/8iByA4GBZEBsidKhqGjh+uXhVwVB1Ca9+S+O9G3BGV1FYeMxzlLn40rjlpH+zIW
-okTLj6e5724+o61kUspioNn9Y77beGf9j3OyUsswttZAFB54tktL+AZKGqEnKjHt
-eqo3xWAZ1clXvXBfjfIAUaRok1y8XfRvDSCcO0CZHj8c+x6SpAT5q5FbeVb6KPnj
-s9p6ppzFbtb7Llm0C+1KOKCL98YRBWPJw7Bg2w86LkpM53xiQPgfk3gd5uwuaWwA
-ZhMb5qBWjjynNY+OrmZ8/+bBQk8XASZfAoIBAFkHOnZOD1JJQ0QvaJ9tuCgHi216
-I8QPMMTdm3ZEDHSYMNwl7ayeseBcmB2zaqBKYz75qcU0SK4lnZkR2wIpbsHZNSVM
-J0WpN6r9G4JdnVi11J04RsfSMjCUr/PTVMmPvw8xPHrCxkJmB+d56olSE80I1Jrx
-djCv1LtSsT10W7FIcY82/cOi4xxGLOA70lDCf+szofQgVP8WvuOA1YaFw98ca8zc
-A401CyNexk24/c3d6C19YW/MppdE0uGMxL/oHsPgwkZAf6LmvF/UF71PsBUEniLc
-YFaJl3wn1cPfBBo9L4sZzyP2qokL8YHdg+wW7b4IOsYwbeqceBvqPtcUUPs=
------END RSA PRIVATE KEY-----
diff --git a/apex/extservices/com.android.extservices.pk8 b/apex/extservices/com.android.extservices.pk8
deleted file mode 100644
index 59585a2..0000000
--- a/apex/extservices/com.android.extservices.pk8
+++ /dev/null
Binary files differ
diff --git a/apex/extservices/com.android.extservices.x509.pem b/apex/extservices/com.android.extservices.x509.pem
deleted file mode 100644
index e0343b8..0000000
--- a/apex/extservices/com.android.extservices.x509.pem
+++ /dev/null
@@ -1,36 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGLTCCBBWgAwIBAgIUdqdMmx/5OsCP3Ew3/hcr7+1ACHEwDQYJKoZIhvcNAQEL
-BQAwgaQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
-DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
-b2lkMSAwHgYDVQQDDBdjb20uYW5kcm9pZC5leHRzZXJ2aWNlczEiMCAGCSqGSIb3
-DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAgFw0yMDAxMTcxMDIxMzZaGA80NzU3
-MTIxMzEwMjEzNlowgaQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
-MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD
-VQQLDAdBbmRyb2lkMSAwHgYDVQQDDBdjb20uYW5kcm9pZC5leHRzZXJ2aWNlczEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCAiIwDQYJKoZIhvcN
-AQEBBQADggIPADCCAgoCggIBANKaSeLGaFRRt779vAtTfG3t2aQZrWOByUYc7yUN
-RdmJqWxU47OL5urYmanWPbz2f972Q9oi8x+8y4ny9SEY3wg0pUbzvKNTXpkxWyG1
-HE2C2zTfzuDDLpDIf2usWynt1wLVhpYC3k+7Yv2vOIK5dKkezh6PfdKmsbDae5DE
-d22tTSYZ5KwNpIWrgQle26cRG5sqhAFdkpgGMF00Huz06cjUoTjs2sNSlXTRBOTP
-CCy8UoRjBivQZkwHbddfsn+Z22ARPG8JDg/n4mEi8C0T6bJeQeirSPkBCkD6Djgq
-7RddJ2eLYZII8l8r6A6x+6cnTkXHaV5g3LUwPvi8XEn9IUuT9WJNRje/vfYLycTQ
-kP415CZMxDvsi1Ul4YsbL3enE89ryGMTpVZPogch/36DG5Sye28yISItNUy3urJa
-OXbg7mh+MwPd4bQaW4CJk+AUweKaF4aV0SZFT+nCewL4xLdGdy889KazlW98NqtK
-hOSxIg1jHkZq48ajuq2A+ns1yDKt1l0f9IYCz3mz/IXInokbkjPvHahJTJ+OMHXO
-THD8e5gBzcK841jJk+H3EsIYOHsp66uy2IgEHN+9pAS6vI0xfrXOYuKzuSL3oxcV
-FlVTimt4xokMMerdcW4KD+MC5NFEip4DUS4JKCyG0wRI3ffEs9Zcpxi3QSibrjLW
-rz+hAgMBAAGjUzBRMB0GA1UdDgQWBBTP2AhZzEUUgtAFlkaMaq+RvY06fDAfBgNV
-HSMEGDAWgBTP2AhZzEUUgtAFlkaMaq+RvY06fDAPBgNVHRMBAf8EBTADAQH/MA0G
-CSqGSIb3DQEBCwUAA4ICAQCbwtfo37j62Sudmt32PCfRN/r5ZNDNNA2JhR8uDUmX
-xXfF5YfDvSKsNLiQKcDagu6a+0C+QnzXHXCBlXZFrTJ8NAVMlmqdHGwoFoYMfJZH
-R1lCTidyFMoMLJ8GRGPJjzDkKnOeAqKMCtKvXoH2r12+JB2/ov4ooLREu/wPkEXT
-OymkyWNP5XLQTKWqfEQyXXFpuwZ+m35Wkr0Fm92mZeJpVeIZPK7M7aK3zyoj7XJP
-YLMsR/AQs8OULdpfNMddAuN3ndlYu03LZlsF6LG5bduaDDcESJ5hdJrgBa/NBKRU
-IbS+q/6WAjYKMNRT/fPGew4wUzlWKi1Ihdk79oaqKKijE1b2JSJD1/SEYiBf+JPE
-bXobUrMbBwFpdhT+YLMF9FsuPQKsUIONaWiO4QcQoY/rQwGxPP6fV8ZbBrUWJewj
-MpSdU9foZNa/TmOAgfS/JxH+nXnG4+H1m8mdNBsxvsYmF2ZuGb/jdEeA2cuHIJDZ
-FJeWwCFxzlCGZJaUsxsnZByADBuufUVaO/9gGs0YQC/JP1i9hK4DyZdKwZpXdLi2
-Nw27Qma4WEIZnMb6Rgk1nTV+7ALcOSIhGgFOOeDTuCGfnEcz2coai5fbD/K6Q7Xu
-IRNyxHQjheZPdei2x912Ex/KqKGfaFaZJxrvCSKdhzxcTFIsO4JuZs+SDpRTKcI7
-Cw==
------END CERTIFICATE-----
diff --git a/apex/extservices/testing/Android.bp b/apex/extservices/testing/Android.bp
deleted file mode 100644
index 88a4724..0000000
--- a/apex/extservices/testing/Android.bp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2020 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.
-
-apex_test {
-    name: "test_com.android.extservices",
-    visibility: [
-        "//system/apex/tests",
-    ],
-    defaults: ["com.android.extservices-defaults"],
-    manifest: "test_manifest.json",
-    file_contexts: ":com.android.extservices-file_contexts",
-    // Test APEX, should never be installed
-    installable: false,
-}
diff --git a/apex/extservices/testing/test_manifest.json b/apex/extservices/testing/test_manifest.json
deleted file mode 100644
index 23a50e3..0000000
--- a/apex/extservices/testing/test_manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "com.android.extservices",
-  "version": 2147483647
-}
diff --git a/api/current.txt b/api/current.txt
index 9ff7cc2..6459eb4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11718,10 +11718,9 @@
     method public long getFirstInstallTime();
     method public android.graphics.drawable.Drawable getIcon(int);
     method public CharSequence getLabel();
+    method public float getLoadingProgress();
     method public String getName();
-    method public float getProgress();
     method public android.os.UserHandle getUser();
-    method public boolean isLoading();
     method public boolean isStartable();
   }
 
@@ -11762,7 +11761,7 @@
     ctor public LauncherApps.Callback();
     method public abstract void onPackageAdded(String, android.os.UserHandle);
     method public abstract void onPackageChanged(String, android.os.UserHandle);
-    method public void onPackageProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float);
+    method public void onPackageLoadingProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float);
     method public abstract void onPackageRemoved(String, android.os.UserHandle);
     method public abstract void onPackagesAvailable(String[], android.os.UserHandle, boolean);
     method public void onPackagesSuspended(String[], android.os.UserHandle);
@@ -31862,6 +31861,15 @@
     method public void onAttached(android.net.wifi.aware.WifiAwareSession);
   }
 
+  public final class AwareResources implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getNumOfAvailableDataPaths();
+    method public int getNumOfAvailablePublishSessions();
+    method public int getNumOfAvailableSubscribeSessions();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.AwareResources> CREATOR;
+  }
+
   public final class Characteristics implements android.os.Parcelable {
     method public int describeContents();
     method public int getMaxMatchFilterLength();
@@ -31964,7 +31972,8 @@
   public class WifiAwareManager {
     method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @Nullable android.os.Handler);
     method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @NonNull android.net.wifi.aware.IdentityChangedListener, @Nullable android.os.Handler);
-    method public android.net.wifi.aware.Characteristics getCharacteristics();
+    method @Nullable public android.net.wifi.aware.AwareResources getAvailableAwareResources();
+    method @Nullable public android.net.wifi.aware.Characteristics getCharacteristics();
     method public boolean isAvailable();
     method public boolean isDeviceAttached();
     method public boolean isInstantCommunicationModeEnabled();
diff --git a/api/system-current.txt b/api/system-current.txt
index 720bf8c..3dd05af 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5725,7 +5725,7 @@
     method @NonNull public android.media.tv.tuner.frontend.AtscFrontendSettings.Builder setModulation(int);
   }
 
-  public class DtmbFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+  public final class DtmbFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
     method public int getBandwidthCapability();
     method public int getCodeRateCapability();
     method public int getGuardIntervalCapability();
@@ -5734,7 +5734,7 @@
     method public int getTransmissionModeCapability();
   }
 
-  public class DtmbFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+  public final class DtmbFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
     method @NonNull public static android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder builder();
     method public int getBandwidth();
     method public int getCodeRate();
@@ -7683,8 +7683,11 @@
     method public double getSuccessfulRxPacketsPerSecond();
     method public double getSuccessfulTxPacketsPerSecond();
     method public boolean isEphemeral();
+    method public boolean isOemPaid();
+    method public boolean isOemPrivate();
     method public boolean isOsuAp();
     method public boolean isPasspointAp();
+    method public boolean isTrusted();
     method @Nullable public static String sanitizeSsid(@Nullable String);
     field public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
     field public static final int INVALID_RSSI = -127; // 0xffffff81
@@ -7910,11 +7913,13 @@
   public final class WifiNetworkSuggestion implements android.os.Parcelable {
     method @NonNull public android.net.wifi.WifiConfiguration getWifiConfiguration();
     method public boolean isOemPaid();
+    method public boolean isOemPrivate();
   }
 
   public static final class WifiNetworkSuggestion.Builder {
     method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) public android.net.wifi.WifiNetworkSuggestion.Builder setCarrierId(int);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setOemPaid(boolean);
+    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setOemPrivate(boolean);
   }
 
   public class WifiScanner {
diff --git a/api/test-current.txt b/api/test-current.txt
index 785463a9..edc422d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -290,6 +290,7 @@
     method @NonNull public android.content.res.Configuration getConfiguration();
     method @Nullable public android.app.PictureInPictureParams getPictureInPictureParams();
     method @NonNull public android.window.WindowContainerToken getToken();
+    method public boolean hasParentTask();
   }
 
   public class TimePickerDialog extends android.app.AlertDialog implements android.content.DialogInterface.OnClickListener android.widget.TimePicker.OnTimeChangedListener {
@@ -970,6 +971,14 @@
     field public static final String SAMPLE_RATE = "android.media.audiotrack.sampleRate";
   }
 
+  public abstract class Image implements java.lang.AutoCloseable {
+    ctor protected Image();
+  }
+
+  public abstract static class Image.Plane {
+    ctor protected Image.Plane();
+  }
+
   public final class MediaCas implements java.lang.AutoCloseable {
     method public void forceResourceLost();
   }
diff --git a/cmds/statsd/src/anomaly/AlarmTracker.h b/cmds/statsd/src/anomaly/AlarmTracker.h
index 2da4a18..406086d 100644
--- a/cmds/statsd/src/anomaly/AlarmTracker.h
+++ b/cmds/statsd/src/anomaly/AlarmTracker.h
@@ -73,6 +73,7 @@
 
     FRIEND_TEST(AlarmTrackerTest, TestTriggerTimestamp);
     FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
+    FRIEND_TEST(ConfigUpdateTest, TestUpdateAlarms);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index 619752c..6aa410b 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -37,14 +37,6 @@
 AnomalyTracker::AnomalyTracker(const Alert& alert, const ConfigKey& configKey)
         : mAlert(alert), mConfigKey(configKey), mNumOfPastBuckets(mAlert.num_buckets() - 1) {
     VLOG("AnomalyTracker() called");
-    if (mAlert.num_buckets() <= 0) {
-        ALOGE("Cannot create AnomalyTracker with %lld buckets", (long long)mAlert.num_buckets());
-        return;
-    }
-    if (!mAlert.has_trigger_if_sum_gt()) {
-        ALOGE("Cannot create AnomalyTracker without threshold");
-        return;
-    }
     resetStorage();  // initialization
 }
 
@@ -52,6 +44,10 @@
     VLOG("~AnomalyTracker() called");
 }
 
+void AnomalyTracker::onConfigUpdated() {
+    mSubscriptions.clear();
+}
+
 void AnomalyTracker::resetStorage() {
     VLOG("resetStorage() called.");
     mPastBuckets.clear();
@@ -259,6 +255,15 @@
     return false;
 }
 
+std::pair<bool, uint64_t> AnomalyTracker::getProtoHash() const {
+    string serializedAlert;
+    if (!mAlert.SerializeToString(&serializedAlert)) {
+        ALOGW("Unable to serialize alert %lld", (long long)mAlert.id());
+        return {false, 0};
+    }
+    return {true, Hash64(serializedAlert)};
+}
+
 void AnomalyTracker::informSubscribers(const MetricDimensionKey& key, int64_t metric_id,
                                        int64_t metricValue) {
     triggerSubscribers(mAlert.id(), metric_id, key, metricValue, mConfigKey, mSubscriptions);
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h
index bf36a3b..9a578ee 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.h
@@ -16,15 +16,15 @@
 
 #pragma once
 
-#include <stdlib.h>
-
 #include <gtest/gtest_prod.h>
+#include <stdlib.h>
 #include <utils/RefBase.h>
 
 #include "AlarmMonitor.h"
 #include "config/ConfigKey.h"
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"  // Alert
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"    // Alert
 #include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h"  // AlertMetadata
+#include "hash.h"
 #include "stats_util.h"  // HashableDimensionKey and DimToValMap
 
 namespace android {
@@ -41,6 +41,9 @@
 
     virtual ~AnomalyTracker();
 
+    // Reset appropriate state on a config update. Clear subscriptions so they can be reset.
+    void onConfigUpdated();
+
     // Add subscriptions that depend on this alert.
     void addSubscription(const Subscription& subscription) {
         mSubscriptions.push_back(subscription);
@@ -106,6 +109,26 @@
         return mNumOfPastBuckets;
     }
 
+    std::pair<bool, uint64_t> getProtoHash() const;
+
+    // Sets an alarm for the given timestamp.
+    // Replaces previous alarm if one already exists.
+    virtual void startAlarm(const MetricDimensionKey& dimensionKey, const int64_t& eventTime) {
+        return;  // The base AnomalyTracker class doesn't have alarms.
+    }
+
+    // Stops the alarm.
+    // If it should have already fired, but hasn't yet (e.g. because the AlarmManager is delayed),
+    // declare the anomaly now.
+    virtual void stopAlarm(const MetricDimensionKey& dimensionKey, const int64_t& timestampNs) {
+        return;  // The base AnomalyTracker class doesn't have alarms.
+    }
+
+    // Stop all the alarms owned by this tracker. Does not declare any anomalies.
+    virtual void cancelAllAlarms() {
+        return;  // The base AnomalyTracker class doesn't have alarms.
+    }
+
     // Declares an anomaly for each alarm in firedAlarms that belongs to this AnomalyTracker,
     // and removes it from firedAlarms. Does NOT remove the alarm from the AlarmMonitor.
     virtual void informAlarmsFired(const int64_t& timestampNs,
@@ -197,6 +220,8 @@
     FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
     FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
     FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
+
+    FRIEND_TEST(ConfigUpdateTest, TestUpdateAlerts);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
index 686d8f9..4641914 100644
--- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
@@ -34,15 +34,15 @@
 
     // Sets an alarm for the given timestamp.
     // Replaces previous alarm if one already exists.
-    void startAlarm(const MetricDimensionKey& dimensionKey, const int64_t& eventTime);
+    void startAlarm(const MetricDimensionKey& dimensionKey, const int64_t& eventTime) override;
 
     // Stops the alarm.
     // If it should have already fired, but hasn't yet (e.g. because the AlarmManager is delayed),
     // declare the anomaly now.
-    void stopAlarm(const MetricDimensionKey& dimensionKey, const int64_t& timestampNs);
+    void stopAlarm(const MetricDimensionKey& dimensionKey, const int64_t& timestampNs) override;
 
     // Stop all the alarms owned by this tracker. Does not declare any anomalies.
-    void cancelAllAlarms();
+    void cancelAllAlarms() override;
 
     // Declares an anomaly for each alarm in firedAlarms that belongs to this DurationAnomalyTracker
     // and removes it from firedAlarms. The AlarmMonitor is not informed.
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index a379847..ac2a8e4 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -9754,6 +9754,7 @@
 
 /**
  * Global display pipeline metrics reported by SurfaceFlinger.
+ * Metrics exist beginning in Android 11.
  * Pulled from:
  *    frameworks/native/services/surfaceflinger/TimeStats/TimeStats.cpp
  */
@@ -9785,18 +9786,48 @@
     // perform due to falling back into GPU composition.
     optional FrameTimingHistogram render_engine_timing = 8
         [(android.os.statsd.log_mode) = MODE_BYTES];
+    // Number of frames where SF saw a frame, based on its frame timeline.
+    // Frame timelines may include transactions without updating buffer contents.
+    // Introduced in Android 12.
+    optional int32 total_timeline_frames = 9;
+    // Number of frames where SF saw a janky frame.
+    // Introduced in Android 12.
+    optional int32 total_janky_frames = 10;
+    // Number of janky frames where SF spent a long time on the CPU.
+    // Introduced in Android 12.
+    optional int32 total_janky_frames_with_long_cpu = 11;
+    // Number of janky frames where SF spent a long time on the GPU.
+    // Introduced in Android 12.
+    optional int32 total_janky_frames_with_long_gpu = 12;
+    // Number of janky frames where SF missed the frame deadline, but there
+    // was not an attributed reason (e.g., maybe HWC missed?)
+    // Introduced in Android 12.
+    optional int32 total_janky_frames_sf_unattributed = 13;
+    // Number of janky frames where the app missed the frame deadline, but
+    // there was not an attributed reason
+    // Introduced in Android 12.
+    optional int32 total_janky_frames_app_unattributed = 14;
+
+    // Next ID: 15
 }
 
 /**
  * Per-layer display pipeline metrics reported by SurfaceFlinger.
- * The number of layers uploaded will be restricted due to size limitations.
+ * Metrics exist beginning in Android 11.
+ * The number of layers uploaded may be restricted due to size limitations.
  * Pulled from:
  *    frameworks/native/services/surfaceflinger/TimeStats/TimeStats.cpp
  */
 message SurfaceflingerStatsLayerInfo {
+    // UID of the application who submitted this layer for presentation
+    // This is intended to be used as a dimension for surfacing rendering
+    // statistics to applications.
+    // Introduced in Android 12.
+    optional int32 uid = 12 [(is_uid) = true];
     // The layer for this set of metrics
-    // For now we can infer that the package name is included in the layer
-    // name.
+    // In many scenarios the package name is included in the layer name, e.g.,
+    // layers created by Window Manager. But this is not a guarantee - in the
+    // general case layer names are arbitrary debug names.
     optional string layer_name = 1;
     // Total number of frames presented
     optional int64 total_frames = 2;
@@ -9830,6 +9861,29 @@
     optional int64 late_acquire_frames = 10;
     // Frames latched early because the desired present time was bad
     optional int64 bad_desired_present_frames = 11;
+    // Number of frames where SF saw a frame, based on its frame timeline.
+    // Frame timelines may include transactions without updating buffer contents.
+    // Introduced in Android 12.
+    optional int32 total_timeline_frames = 13;
+    // Number of frames where SF saw a janky frame.
+    // Introduced in Android 12.
+    optional int32 total_janky_frames = 14;
+    // Number of janky frames where SF spent a long time on the CPU.
+    // Introduced in Android 12.
+    optional int32 total_janky_frames_with_long_cpu = 15;
+    // Number of janky frames where SF spent a long time on the GPU.
+    // Introduced in Android 12.
+    optional int32 total_janky_frames_with_long_gpu = 16;
+    // Number of janky frames where SF missed the frame deadline, but there
+    // was not an attributed reason (e.g., maybe HWC missed?)
+    // Introduced in Android 12.
+    optional int32 total_janky_frames_sf_unattributed = 17;
+    // Number of janky frames where the app missed the frame deadline, but
+    // there was not an attributed reason
+    // Introduced in Android 12.
+    optional int32 total_janky_frames_app_unattributed = 18;
+
+    // Next ID: 19
 }
 
 /**
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index b2c0b32..8869241 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -234,14 +234,26 @@
             return nullptr;
         }
     }
-    sp<DurationAnomalyTracker> anomalyTracker =
-        new DurationAnomalyTracker(alert, mConfigKey, anomalyAlarmMonitor);
-    if (anomalyTracker != nullptr) {
-        mAnomalyTrackers.push_back(anomalyTracker);
-    }
+    sp<AnomalyTracker> anomalyTracker =
+            new DurationAnomalyTracker(alert, mConfigKey, anomalyAlarmMonitor);
+    addAnomalyTrackerLocked(anomalyTracker);
     return anomalyTracker;
 }
 
+// Adds an AnomalyTracker that has already been created.
+// Note: this gets called on config updates, and will only get called if the metric and the
+// associated alert are preserved, which means the AnomalyTracker must be a DurationAnomalyTracker.
+void DurationMetricProducer::addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    addAnomalyTrackerLocked(anomalyTracker);
+}
+
+void DurationMetricProducer::addAnomalyTrackerLocked(sp<AnomalyTracker>& anomalyTracker) {
+    mAnomalyTrackers.push_back(anomalyTracker);
+    for (const auto& [_, durationTracker] : mCurrentSlicedDurationTrackerMap) {
+        durationTracker->addAnomalyTracker(anomalyTracker);
+    }
+}
 void DurationMetricProducer::onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
                                             const HashableDimensionKey& primaryKey,
                                             const FieldValue& oldState,
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 01198a9..5feb09f 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -55,6 +55,8 @@
     sp<AnomalyTracker> addAnomalyTracker(const Alert &alert,
                                          const sp<AlarmMonitor>& anomalyAlarmMonitor) override;
 
+    void addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker) override;
+
     void onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
                         const HashableDimensionKey& primaryKey, const FieldValue& oldState,
                         const FieldValue& newState) override;
@@ -128,6 +130,8 @@
             std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
             std::vector<int>& metricsWithActivation) override;
 
+    void addAnomalyTrackerLocked(sp<AnomalyTracker>& anomalyTracker);
+
     const DurationMetric_AggregationType mAggregationType;
 
     // Index of the SimpleAtomMatcher which defines the start.
@@ -164,9 +168,6 @@
     std::unique_ptr<DurationTracker> createDurationTracker(
             const MetricDimensionKey& eventKey) const;
 
-    // This hides the base class's std::vector<sp<AnomalyTracker>> mAnomalyTrackers
-    std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers;
-
     // Util function to check whether the specified dimension hits the guardrail.
     bool hitGuardRailLocked(const MetricDimensionKey& newKey);
 
@@ -185,6 +186,7 @@
     FRIEND_TEST(DurationMetricProducerTest_PartialBucket, TestMaxDurationWithSplitInNextBucket);
 
     FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
+    FRIEND_TEST(ConfigUpdateTest, TestUpdateAlerts);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 95a7d40..5b321a0 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -101,6 +101,7 @@
     }
     mEventActivationMap = newEventActivationMap;
     mEventDeactivationMap = newEventDeactivationMap;
+    mAnomalyTrackers.clear();
     return true;
 }
 
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 92c1a6e..0dc8eda 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -155,6 +155,7 @@
     // Update appropriate state on config updates. Primarily, all indices need to be updated.
     // This metric and all of its dependencies are guaranteed to be preserved across the update.
     // This function also updates several maps used by metricsManager.
+    // This function clears all anomaly trackers. All anomaly trackers need to be added again.
     bool onConfigUpdated(
             const StatsdConfig& config, const int configIndex, const int metricIndex,
             const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -237,9 +238,6 @@
                 dumpLatency, str_set, protoOutput);
     }
 
-    // Update appropriate state on config updates. Primarily, all indices need to be updated.
-    // This metric and all of its dependencies are guaranteed to be preserved across the update.
-    // This function also updates several maps used by metricsManager.
     virtual bool onConfigUpdatedLocked(
             const StatsdConfig& config, const int configIndex, const int metricIndex,
             const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -338,16 +336,20 @@
         return mSlicedStateAtoms;
     }
 
-    /* If alert is valid, adds an AnomalyTracker and returns it. If invalid, returns nullptr. */
+    /* Adds an AnomalyTracker and returns it. */
     virtual sp<AnomalyTracker> addAnomalyTracker(const Alert &alert,
                                                  const sp<AlarmMonitor>& anomalyAlarmMonitor) {
         std::lock_guard<std::mutex> lock(mMutex);
         sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, mConfigKey);
-        if (anomalyTracker != nullptr) {
-            mAnomalyTrackers.push_back(anomalyTracker);
-        }
+        mAnomalyTrackers.push_back(anomalyTracker);
         return anomalyTracker;
     }
+
+    /* Adds an AnomalyTracker that has already been created */
+    virtual void addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker) {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mAnomalyTrackers.push_back(anomalyTracker);
+    }
     // End: getters/setters
 protected:
     /**
@@ -571,6 +573,7 @@
     FRIEND_TEST(ConfigUpdateTest, TestUpdateGaugeMetrics);
     FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
     FRIEND_TEST(ConfigUpdateTest, TestUpdateMetricsMultipleTypes);
+    FRIEND_TEST(ConfigUpdateTest, TestUpdateAlerts);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index ab0d286..d80f9db 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -209,6 +209,9 @@
     map<int64_t, uint64_t> newStateProtoHashes;
     vector<sp<MetricProducer>> newMetricProducers;
     unordered_map<int64_t, int> newMetricProducerMap;
+    vector<sp<AnomalyTracker>> newAnomalyTrackers;
+    unordered_map<int64_t, int> newAlertTrackerMap;
+    vector<sp<AlarmTracker>> newPeriodicAlarmTrackers;
     mTagIds.clear();
     mConditionToMetricMap.clear();
     mTrackerToMetricMap.clear();
@@ -221,11 +224,13 @@
             mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
             timeBaseNs, currentTimeNs, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap,
             mAllConditionTrackers, mConditionTrackerMap, mAllMetricProducers, mMetricProducerMap,
-            mStateProtoHashes, mTagIds, newAtomMatchingTrackers, newAtomMatchingTrackerMap,
-            newConditionTrackers, newConditionTrackerMap, newMetricProducers, newMetricProducerMap,
-            mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap,
-            mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap,
-            mMetricIndexesWithActivation, newStateProtoHashes, mNoReportMetricIds);
+            mAllAnomalyTrackers, mAlertTrackerMap, mStateProtoHashes, mTagIds,
+            newAtomMatchingTrackers, newAtomMatchingTrackerMap, newConditionTrackers,
+            newConditionTrackerMap, newMetricProducers, newMetricProducerMap, newAnomalyTrackers,
+            newAlertTrackerMap, newPeriodicAlarmTrackers, mConditionToMetricMap,
+            mTrackerToMetricMap, mTrackerToConditionMap, mActivationAtomTrackerToMetricMap,
+            mDeactivationAtomTrackerToMetricMap, mMetricIndexesWithActivation, newStateProtoHashes,
+            mNoReportMetricIds);
     mAllAtomMatchingTrackers = newAtomMatchingTrackers;
     mAtomMatchingTrackerMap = newAtomMatchingTrackerMap;
     mAllConditionTrackers = newConditionTrackers;
@@ -233,6 +238,9 @@
     mAllMetricProducers = newMetricProducers;
     mMetricProducerMap = newMetricProducerMap;
     mStateProtoHashes = newStateProtoHashes;
+    mAllAnomalyTrackers = newAnomalyTrackers;
+    mAlertTrackerMap = newAlertTrackerMap;
+    mAllPeriodicAlarmTrackers = newPeriodicAlarmTrackers;
     return mConfigValid;
 }
 
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 657b2e4..cf1f437 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -71,7 +71,7 @@
                     sp<ConditionWizard> wizard, int conditionIndex, bool nesting,
                     int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs,
                     int64_t bucketSizeNs, bool conditionSliced, bool fullLink,
-                    const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
+                    const std::vector<sp<AnomalyTracker>>& anomalyTrackers)
         : mConfigKey(key),
           mTrackerId(id),
           mEventKey(eventKey),
@@ -93,6 +93,7 @@
         sp<ConditionWizard> tmpWizard = mWizard;
         mWizard = wizard;
         mConditionTrackerIndex = conditionTrackerIndex;
+        mAnomalyTrackers.clear();
     };
 
     virtual void noteStart(const HashableDimensionKey& key, bool condition, const int64_t eventTime,
@@ -120,7 +121,7 @@
             std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) = 0;
 
     // Predict the anomaly timestamp given the current status.
-    virtual int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
+    virtual int64_t predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
                                               const int64_t currentTimestamp) const = 0;
     // Dump internal states for debugging
     virtual void dumpStates(FILE* out, bool verbose) const = 0;
@@ -132,6 +133,10 @@
     // Replace old value with new value for the given state atom.
     virtual void updateCurrentStateKey(const int32_t atomId, const FieldValue& newState) = 0;
 
+    void addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker) {
+        mAnomalyTrackers.push_back(anomalyTracker);
+    }
+
 protected:
     int64_t getCurrentBucketEndTimeNs() const {
         return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
@@ -218,13 +223,14 @@
 
     bool mHasLinksToAllConditionDimensionsInTracker;
 
-    std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers;
+    std::vector<sp<AnomalyTracker>> mAnomalyTrackers;
 
     FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
     FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm);
     FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm);
 
     FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
+    FRIEND_TEST(ConfigUpdateTest, TestUpdateAlerts);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index ee4e167..62f4982 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -30,7 +30,7 @@
                                        int64_t currentBucketStartNs, int64_t currentBucketNum,
                                        int64_t startTimeNs, int64_t bucketSizeNs,
                                        bool conditionSliced, bool fullLink,
-                                       const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
+                                       const vector<sp<AnomalyTracker>>& anomalyTrackers)
     : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs,
                       currentBucketNum, startTimeNs, bucketSizeNs, conditionSliced, fullLink,
                       anomalyTrackers) {
@@ -288,7 +288,7 @@
     // Note that we don't update mDuration here since it's only updated during noteStop.
 }
 
-int64_t MaxDurationTracker::predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
+int64_t MaxDurationTracker::predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
                                                       const int64_t currentTimestamp) const {
     // The allowed time we can continue in the current state is the
     // (anomaly threshold) - max(elapsed time of the started mInfos).
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index 2891c6e..be2707c 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -29,12 +29,10 @@
 class MaxDurationTracker : public DurationTracker {
 public:
     MaxDurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
-                       sp<ConditionWizard> wizard, int conditionIndex,
-                       bool nesting,
-                       int64_t currentBucketStartNs, int64_t currentBucketNum,
-                       int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced,
-                       bool fullLink,
-                       const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
+                       sp<ConditionWizard> wizard, int conditionIndex, bool nesting,
+                       int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs,
+                       int64_t bucketSizeNs, bool conditionSliced, bool fullLink,
+                       const std::vector<sp<AnomalyTracker>>& anomalyTrackers);
 
     MaxDurationTracker(const MaxDurationTracker& tracker) = default;
 
@@ -57,7 +55,7 @@
     void onStateChanged(const int64_t timestamp, const int32_t atomId,
                         const FieldValue& newState) override;
 
-    int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
+    int64_t predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
                                       const int64_t currentTimestamp) const override;
     void dumpStates(FILE* out, bool verbose) const override;
 
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index 0d49bbc..247e2e0 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -28,7 +28,7 @@
         const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
         sp<ConditionWizard> wizard, int conditionIndex, bool nesting, int64_t currentBucketStartNs,
         int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced,
-        bool fullLink, const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
+        bool fullLink, const vector<sp<AnomalyTracker>>& anomalyTrackers)
     : DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs,
                       currentBucketNum, startTimeNs, bucketSizeNs, conditionSliced, fullLink,
                       anomalyTrackers),
@@ -344,9 +344,8 @@
     updateCurrentStateKey(atomId, newState);
 }
 
-int64_t OringDurationTracker::predictAnomalyTimestampNs(
-        const DurationAnomalyTracker& anomalyTracker, const int64_t eventTimestampNs) const {
-
+int64_t OringDurationTracker::predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
+                                                        const int64_t eventTimestampNs) const {
     // The anomaly threshold.
     const int64_t thresholdNs = anomalyTracker.getAnomalyThreshold();
 
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index bd8017a..6eddee7 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -31,7 +31,7 @@
                          int conditionIndex, bool nesting, int64_t currentBucketStartNs,
                          int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs,
                          bool conditionSliced, bool fullLink,
-                         const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
+                         const std::vector<sp<AnomalyTracker>>& anomalyTrackers);
 
     OringDurationTracker(const OringDurationTracker& tracker) = default;
 
@@ -54,7 +54,7 @@
             int64_t timestampNs,
             std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) override;
 
-    int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
+    int64_t predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
                                       const int64_t currentTimestamp) const override;
     void dumpStates(FILE* out, bool verbose) const override;
 
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
index 335f775..6372361 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -115,7 +115,6 @@
                                 vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
                                 set<int64_t>& replacedMatchers) {
     const int atomMatcherCount = config.atom_matcher_size();
-
     vector<AtomMatcher> matcherProtos;
     matcherProtos.reserve(atomMatcherCount);
     newAtomMatchingTrackers.reserve(atomMatcherCount);
@@ -891,6 +890,111 @@
     return true;
 }
 
+bool determineAlertUpdateStatus(const Alert& alert,
+                                const unordered_map<int64_t, int>& oldAlertTrackerMap,
+                                const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+                                const set<int64_t>& replacedMetrics, UpdateStatus& updateStatus) {
+    // Check if new alert.
+    const auto& oldAnomalyTrackerIt = oldAlertTrackerMap.find(alert.id());
+    if (oldAnomalyTrackerIt == oldAlertTrackerMap.end()) {
+        updateStatus = UPDATE_NEW;
+        return true;
+    }
+
+    // This is an existing alert, check if it has changed.
+    string serializedAlert;
+    if (!alert.SerializeToString(&serializedAlert)) {
+        ALOGW("Unable to serialize alert %lld", (long long)alert.id());
+        return false;
+    }
+    uint64_t newProtoHash = Hash64(serializedAlert);
+    const auto [success, oldProtoHash] =
+            oldAnomalyTrackers[oldAnomalyTrackerIt->second]->getProtoHash();
+    if (!success) {
+        return false;
+    }
+    if (newProtoHash != oldProtoHash) {
+        updateStatus = UPDATE_REPLACE;
+        return true;
+    }
+
+    // Check if the metric this alert relies on has changed.
+    if (replacedMetrics.find(alert.metric_id()) != replacedMetrics.end()) {
+        updateStatus = UPDATE_REPLACE;
+        return true;
+    }
+
+    updateStatus = UPDATE_PRESERVE;
+    return true;
+}
+
+bool updateAlerts(const StatsdConfig& config, const unordered_map<int64_t, int>& metricProducerMap,
+                  const set<int64_t>& replacedMetrics,
+                  const unordered_map<int64_t, int>& oldAlertTrackerMap,
+                  const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+                  const sp<AlarmMonitor>& anomalyAlarmMonitor,
+                  vector<sp<MetricProducer>>& allMetricProducers,
+                  unordered_map<int64_t, int>& newAlertTrackerMap,
+                  vector<sp<AnomalyTracker>>& newAnomalyTrackers) {
+    int alertCount = config.alert_size();
+    vector<UpdateStatus> alertUpdateStatuses(alertCount);
+    for (int i = 0; i < alertCount; i++) {
+        if (!determineAlertUpdateStatus(config.alert(i), oldAlertTrackerMap, oldAnomalyTrackers,
+                                        replacedMetrics, alertUpdateStatuses[i])) {
+            return false;
+        }
+    }
+
+    for (int i = 0; i < alertCount; i++) {
+        const Alert& alert = config.alert(i);
+        newAlertTrackerMap[alert.id()] = newAnomalyTrackers.size();
+        switch (alertUpdateStatuses[i]) {
+            case UPDATE_PRESERVE: {
+                // Find the alert and update it.
+                const auto& oldAnomalyTrackerIt = oldAlertTrackerMap.find(alert.id());
+                if (oldAnomalyTrackerIt == oldAlertTrackerMap.end()) {
+                    ALOGW("Could not find AnomalyTracker %lld in the previous config, but "
+                          "expected it to be there",
+                          (long long)alert.id());
+                    return false;
+                }
+                sp<AnomalyTracker> anomalyTracker = oldAnomalyTrackers[oldAnomalyTrackerIt->second];
+                anomalyTracker->onConfigUpdated();
+                // Add the alert to the relevant metric.
+                const auto& metricProducerIt = metricProducerMap.find(alert.metric_id());
+                if (metricProducerIt == metricProducerMap.end()) {
+                    ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
+                          (long long)alert.metric_id());
+                    return false;
+                }
+                allMetricProducers[metricProducerIt->second]->addAnomalyTracker(anomalyTracker);
+                newAnomalyTrackers.push_back(anomalyTracker);
+                break;
+            }
+            case UPDATE_REPLACE:
+            case UPDATE_NEW: {
+                optional<sp<AnomalyTracker>> anomalyTracker = createAnomalyTracker(
+                        alert, anomalyAlarmMonitor, metricProducerMap, allMetricProducers);
+                if (!anomalyTracker) {
+                    return false;
+                }
+                newAnomalyTrackers.push_back(anomalyTracker.value());
+                break;
+            }
+            default: {
+                ALOGE("Alert \"%lld\" update state is unknown. This should never happen",
+                      (long long)alert.id());
+                return false;
+            }
+        }
+    }
+    if (!initSubscribersForSubscriptionType(config, Subscription::ALERT, newAlertTrackerMap,
+                                            newAnomalyTrackers)) {
+        return false;
+    }
+    return true;
+}
+
 bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
                         const sp<StatsPullerManager>& pullerManager,
                         const sp<AlarmMonitor>& anomalyAlarmMonitor,
@@ -902,6 +1006,8 @@
                         const unordered_map<int64_t, int>& oldConditionTrackerMap,
                         const vector<sp<MetricProducer>>& oldMetricProducers,
                         const unordered_map<int64_t, int>& oldMetricProducerMap,
+                        const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+                        const unordered_map<int64_t, int>& oldAlertTrackerMap,
                         const map<int64_t, uint64_t>& oldStateProtoHashes, set<int>& allTagIds,
                         vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
                         unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
@@ -909,6 +1015,9 @@
                         unordered_map<int64_t, int>& newConditionTrackerMap,
                         vector<sp<MetricProducer>>& newMetricProducers,
                         unordered_map<int64_t, int>& newMetricProducerMap,
+                        vector<sp<AnomalyTracker>>& newAnomalyTrackers,
+                        unordered_map<int64_t, int>& newAlertTrackerMap,
+                        vector<sp<AlarmTracker>>& newPeriodicAlarmTrackers,
                         unordered_map<int, vector<int>>& conditionToMetricMap,
                         unordered_map<int, vector<int>>& trackerToMetricMap,
                         unordered_map<int, vector<int>>& trackerToConditionMap,
@@ -962,10 +1071,23 @@
                        newMetricProducerMap, newMetricProducers, conditionToMetricMap,
                        trackerToMetricMap, noReportMetricIds, activationTrackerToMetricMap,
                        deactivationTrackerToMetricMap, metricsWithActivation, replacedMetrics)) {
-        ALOGE("initMetricProducers failed");
+        ALOGE("updateMetrics failed");
         return false;
     }
 
+    if (!updateAlerts(config, newMetricProducerMap, replacedMetrics, oldAlertTrackerMap,
+                      oldAnomalyTrackers, anomalyAlarmMonitor, newMetricProducers,
+                      newAlertTrackerMap, newAnomalyTrackers)) {
+        ALOGE("updateAlerts failed");
+        return false;
+    }
+
+    // Alarms do not have any state, so we can reuse the initialization logic.
+    if (!initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+                    newPeriodicAlarmTrackers)) {
+        ALOGE("initAlarms failed");
+        return false;
+    }
     return true;
 }
 
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
index 3f1c532..178a9d2 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
@@ -19,6 +19,7 @@
 #include <vector>
 
 #include "anomaly/AlarmMonitor.h"
+#include "anomaly/AlarmTracker.h"
 #include "condition/ConditionTracker.h"
 #include "external/StatsPullerManager.h"
 #include "matchers/AtomMatchingTracker.h"
@@ -189,6 +190,45 @@
         std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
         std::vector<int>& metricsWithActivation, std::set<int64_t>& replacedMetrics);
 
+// Function to determine the update status (preserve/replace/new) of an alert.
+// [alert]: the input Alert
+// [oldAlertTrackerMap]: alert id to index mapping in the existing MetricsManager
+// [oldAnomalyTrackers]: stores the existing AnomalyTrackers
+// [replacedMetrics]: set of replaced metric ids. alerts using these metrics must be replaced
+// output:
+// [updateStatus]: update status of the alert. Will be changed from UPDATE_UNKNOWN
+// Returns whether the function was successful or not.
+bool determineAlertUpdateStatus(const Alert& alert,
+                                const std::unordered_map<int64_t, int>& oldAlertTrackerMap,
+                                const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+                                const std::set<int64_t>& replacedMetrics,
+                                UpdateStatus& updateStatus);
+
+// Update MetricProducers.
+// input:
+// [config]: the input config
+// [metricProducerMap]: metric id to index mapping in the new config
+// [replacedMetrics]: set of metric ids that have changed and were replaced
+// [oldAlertTrackerMap]: alert id to index mapping in the existing MetricsManager.
+// [oldAnomalyTrackers]: stores the existing AnomalyTrackers
+// [anomalyAlarmMonitor]: AlarmMonitor used for duration metric anomaly detection
+// [allMetricProducers]: stores the sp of the metric producers, AnomalyTrackers need to be added.
+// [stateAtomIdMap]: contains the mapping from state ids to atom ids
+// [allStateGroupMaps]: contains the mapping from atom ids and state values to
+//                      state group ids for all states
+// output:
+// [newAlertTrackerMap]: mapping of alert id to index in the new config
+// [newAnomalyTrackers]: contains the list of sp to the AnomalyTrackers created.
+bool updateAlerts(const StatsdConfig& config,
+                  const std::unordered_map<int64_t, int>& metricProducerMap,
+                  const std::set<int64_t>& replacedMetrics,
+                  const std::unordered_map<int64_t, int>& oldAlertTrackerMap,
+                  const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+                  const sp<AlarmMonitor>& anomalyAlarmMonitor,
+                  std::vector<sp<MetricProducer>>& allMetricProducers,
+                  std::unordered_map<int64_t, int>& newAlertTrackerMap,
+                  std::vector<sp<AnomalyTracker>>& newAnomalyTrackers);
+
 // Updates the existing MetricsManager from a new StatsdConfig.
 // Parameters are the members of MetricsManager. See MetricsManager for declaration.
 bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
@@ -202,6 +242,8 @@
                         const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
                         const std::vector<sp<MetricProducer>>& oldMetricProducers,
                         const std::unordered_map<int64_t, int>& oldMetricProducerMap,
+                        const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+                        const std::unordered_map<int64_t, int>& oldAlertTrackerMap,
                         const std::map<int64_t, uint64_t>& oldStateProtoHashes,
                         std::set<int>& allTagIds,
                         std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
@@ -210,6 +252,9 @@
                         std::unordered_map<int64_t, int>& newConditionTrackerMap,
                         std::vector<sp<MetricProducer>>& newMetricProducers,
                         std::unordered_map<int64_t, int>& newMetricProducerMap,
+                        std::vector<sp<AnomalyTracker>>& newAlertTrackers,
+                        std::unordered_map<int64_t, int>& newAlertTrackerMap,
+                        std::vector<sp<AlarmTracker>>& newPeriodicAlarmTrackers,
                         std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
                         std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
                         std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index 8fc039a..4474df4 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -814,6 +814,35 @@
                                     pullerManager, eventActivationMap, eventDeactivationMap)};
 }
 
+optional<sp<AnomalyTracker>> createAnomalyTracker(
+        const Alert& alert, const sp<AlarmMonitor>& anomalyAlarmMonitor,
+        const unordered_map<int64_t, int>& metricProducerMap,
+        vector<sp<MetricProducer>>& allMetricProducers) {
+    const auto& itr = metricProducerMap.find(alert.metric_id());
+    if (itr == metricProducerMap.end()) {
+        ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
+              (long long)alert.metric_id());
+        return nullopt;
+    }
+    if (!alert.has_trigger_if_sum_gt()) {
+        ALOGW("invalid alert: missing threshold");
+        return nullopt;
+    }
+    if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
+        ALOGW("invalid alert: threshold=%f num_buckets= %d", alert.trigger_if_sum_gt(),
+              alert.num_buckets());
+        return nullopt;
+    }
+    const int metricIndex = itr->second;
+    sp<MetricProducer> metric = allMetricProducers[metricIndex];
+    sp<AnomalyTracker> anomalyTracker = metric->addAnomalyTracker(alert, anomalyAlarmMonitor);
+    if (anomalyTracker == nullptr) {
+        // The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
+        return nullopt;
+    }
+    return {anomalyTracker};
+}
+
 bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
                               unordered_map<int64_t, int>& atomMatchingTrackerMap,
                               vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -1079,49 +1108,17 @@
                 vector<sp<AnomalyTracker>>& allAnomalyTrackers) {
     for (int i = 0; i < config.alert_size(); i++) {
         const Alert& alert = config.alert(i);
-        const auto& itr = metricProducerMap.find(alert.metric_id());
-        if (itr == metricProducerMap.end()) {
-            ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
-                  (long long)alert.metric_id());
-            return false;
-        }
-        if (!alert.has_trigger_if_sum_gt()) {
-            ALOGW("invalid alert: missing threshold");
-            return false;
-        }
-        if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
-            ALOGW("invalid alert: threshold=%f num_buckets= %d", alert.trigger_if_sum_gt(),
-                  alert.num_buckets());
-            return false;
-        }
-        const int metricIndex = itr->second;
-        sp<MetricProducer> metric = allMetricProducers[metricIndex];
-        sp<AnomalyTracker> anomalyTracker = metric->addAnomalyTracker(alert, anomalyAlarmMonitor);
-        if (anomalyTracker == nullptr) {
-            // The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
-            return false;
-        }
         alertTrackerMap.insert(std::make_pair(alert.id(), allAnomalyTrackers.size()));
-        allAnomalyTrackers.push_back(anomalyTracker);
+        optional<sp<AnomalyTracker>> anomalyTracker = createAnomalyTracker(
+                alert, anomalyAlarmMonitor, metricProducerMap, allMetricProducers);
+        if (!anomalyTracker) {
+            return false;
+        }
+        allAnomalyTrackers.push_back(anomalyTracker.value());
     }
-    for (int i = 0; i < config.subscription_size(); ++i) {
-        const Subscription& subscription = config.subscription(i);
-        if (subscription.rule_type() != Subscription::ALERT) {
-            continue;
-        }
-        if (subscription.subscriber_information_case() ==
-            Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
-            ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
-            return false;
-        }
-        const auto& itr = alertTrackerMap.find(subscription.rule_id());
-        if (itr == alertTrackerMap.end()) {
-            ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
-                  (long long)subscription.id(), (long long)subscription.rule_id());
-            return false;
-        }
-        const int anomalyTrackerIndex = itr->second;
-        allAnomalyTrackers[anomalyTrackerIndex]->addSubscription(subscription);
+    if (!initSubscribersForSubscriptionType(config, Subscription::ALERT, alertTrackerMap,
+                                            allAnomalyTrackers)) {
+        return false;
     }
     return true;
 }
@@ -1146,24 +1143,9 @@
         allAlarmTrackers.push_back(
                 new AlarmTracker(startMillis, currentTimeMillis, alarm, key, periodicAlarmMonitor));
     }
-    for (int i = 0; i < config.subscription_size(); ++i) {
-        const Subscription& subscription = config.subscription(i);
-        if (subscription.rule_type() != Subscription::ALARM) {
-            continue;
-        }
-        if (subscription.subscriber_information_case() ==
-            Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
-            ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
-            return false;
-        }
-        const auto& itr = alarmTrackerMap.find(subscription.rule_id());
-        if (itr == alarmTrackerMap.end()) {
-            ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
-                  (long long)subscription.id(), (long long)subscription.rule_id());
-            return false;
-        }
-        const int trackerIndex = itr->second;
-        allAlarmTrackers[trackerIndex]->addSubscription(subscription);
+    if (!initSubscribersForSubscriptionType(config, Subscription::ALARM, alarmTrackerMap,
+                                            allAlarmTrackers)) {
+        return false;
     }
     return true;
 }
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index e4585cd..84e1e4e 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -188,6 +188,41 @@
         std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
         std::vector<int>& metricsWithActivation);
 
+// Creates an AnomalyTracker and adds it to the appropriate metric.
+// Returns an sp to the AnomalyTracker, or nullopt if there was an error.
+optional<sp<AnomalyTracker>> createAnomalyTracker(
+        const Alert& alert, const sp<AlarmMonitor>& anomalyAlarmMonitor,
+        const std::unordered_map<int64_t, int>& metricProducerMap,
+        std::vector<sp<MetricProducer>>& allMetricProducers);
+
+// Templated function for adding subscriptions to alarms or alerts. Returns true if successful.
+template <typename T>
+bool initSubscribersForSubscriptionType(const StatsdConfig& config,
+                                        const Subscription_RuleType ruleType,
+                                        const std::unordered_map<int64_t, int>& ruleMap,
+                                        std::vector<T>& allRules) {
+    for (int i = 0; i < config.subscription_size(); ++i) {
+        const Subscription& subscription = config.subscription(i);
+        if (subscription.rule_type() != ruleType) {
+            continue;
+        }
+        if (subscription.subscriber_information_case() ==
+            Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
+            ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
+            return false;
+        }
+        const auto& itr = ruleMap.find(subscription.rule_id());
+        if (itr == ruleMap.end()) {
+            ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
+                  (long long)subscription.id(), (long long)subscription.rule_id());
+            return false;
+        }
+        const int ruleIndex = itr->second;
+        allRules[ruleIndex]->addSubscription(subscription);
+    }
+    return true;
+}
+
 // Helper functions for MetricsManager to initialize from StatsdConfig.
 // *Note*: only initStatsdConfig() should be called from outside.
 // All other functions are intermediate
@@ -271,6 +306,12 @@
         std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
         std::vector<int>& metricsWithActivation);
 
+// Initialize alarms
+// Is called both on initialize new configs and config updates since alarms do not have any state.
+bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
+                const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
+                const int64_t currentTimeNs, std::vector<sp<AlarmTracker>>& allAlarmTrackers);
+
 // Initialize MetricsManager from StatsdConfig.
 // Parameters are the members of MetricsManager. See MetricsManager for declaration.
 bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
index 4fa9bf6..66bab4e 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -52,11 +52,15 @@
 namespace {
 
 ConfigKey key(123, 456);
-const int64_t timeBaseNs = 1000;
+const int64_t timeBaseNs = 1000 * NS_PER_SEC;
+
 sp<UidMap> uidMap = new UidMap();
 sp<StatsPullerManager> pullerManager = new StatsPullerManager();
 sp<AlarmMonitor> anomalyAlarmMonitor;
-sp<AlarmMonitor> periodicAlarmMonitor;
+sp<AlarmMonitor> periodicAlarmMonitor = new AlarmMonitor(
+        /*minDiffToUpdateRegisteredAlarmTimeSec=*/0,
+        [](const shared_ptr<IStatsCompanionService>&, int64_t) {},
+        [](const shared_ptr<IStatsCompanionService>&) {});
 set<int> allTagIds;
 vector<sp<AtomMatchingTracker>> oldAtomMatchingTrackers;
 unordered_map<int64_t, int> oldAtomMatchingTrackerMap;
@@ -65,13 +69,13 @@
 vector<sp<MetricProducer>> oldMetricProducers;
 unordered_map<int64_t, int> oldMetricProducerMap;
 std::vector<sp<AnomalyTracker>> oldAnomalyTrackers;
+unordered_map<int64_t, int> oldAlertTrackerMap;
 std::vector<sp<AlarmTracker>> oldAlarmTrackers;
 unordered_map<int, std::vector<int>> tmpConditionToMetricMap;
 unordered_map<int, std::vector<int>> tmpTrackerToMetricMap;
 unordered_map<int, std::vector<int>> tmpTrackerToConditionMap;
 unordered_map<int, std::vector<int>> tmpActivationAtomTrackerToMetricMap;
 unordered_map<int, std::vector<int>> tmpDeactivationAtomTrackerToMetricMap;
-unordered_map<int64_t, int> alertTrackerMap;
 vector<int> metricsWithActivation;
 map<int64_t, uint64_t> oldStateHashes;
 std::set<int64_t> noReportMetricIds;
@@ -96,7 +100,7 @@
         tmpTrackerToConditionMap.clear();
         tmpActivationAtomTrackerToMetricMap.clear();
         tmpDeactivationAtomTrackerToMetricMap.clear();
-        alertTrackerMap.clear();
+        oldAlertTrackerMap.clear();
         metricsWithActivation.clear();
         oldStateHashes.clear();
         noReportMetricIds.clear();
@@ -111,7 +115,7 @@
             oldConditionTrackers, oldConditionTrackerMap, oldMetricProducers, oldMetricProducerMap,
             oldAnomalyTrackers, oldAlarmTrackers, tmpConditionToMetricMap, tmpTrackerToMetricMap,
             tmpTrackerToConditionMap, tmpActivationAtomTrackerToMetricMap,
-            tmpDeactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+            tmpDeactivationAtomTrackerToMetricMap, oldAlertTrackerMap, metricsWithActivation,
             oldStateHashes, noReportMetricIds);
 }
 
@@ -188,6 +192,32 @@
     }
     return metric;
 }
+
+Alert createAlert(string name, int64_t metricId, int buckets, int64_t triggerSum) {
+    Alert alert;
+    alert.set_id(StringToId(name));
+    alert.set_metric_id(metricId);
+    alert.set_num_buckets(buckets);
+    alert.set_trigger_if_sum_gt(triggerSum);
+    return alert;
+}
+
+Subscription createSubscription(string name, Subscription_RuleType type, int64_t ruleId) {
+    Subscription subscription;
+    subscription.set_id(StringToId(name));
+    subscription.set_rule_type(type);
+    subscription.set_rule_id(ruleId);
+    subscription.mutable_broadcast_subscriber_details();
+    return subscription;
+}
+
+Alarm createAlarm(string name, int64_t offsetMillis, int64_t periodMillis) {
+    Alarm alarm;
+    alarm.set_id(StringToId(name));
+    alarm.set_offset_millis(offsetMillis);
+    alarm.set_period_millis(periodMillis);
+    return alarm;
+}
 }  // anonymous namespace
 
 TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) {
@@ -3243,6 +3273,305 @@
     // Only reference to the old wizard should be the one in the test.
     EXPECT_EQ(oldConditionWizard->getStrongCount(), 1);
 }
+
+TEST_F(ConfigUpdateTest, TestAlertPreserve) {
+    StatsdConfig config;
+    AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+    *config.add_atom_matcher() = whatMatcher;
+
+    *config.add_count_metric() = createCountMetric("VALUE1", whatMatcher.id(), nullopt, {});
+
+    Alert alert = createAlert("Alert1", config.count_metric(0).id(), 1, 1);
+    *config.add_alert() = alert;
+    EXPECT_TRUE(initConfig(config));
+
+    UpdateStatus updateStatus = UPDATE_UNKNOWN;
+    EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
+                                           /*replacedMetrics*/ {}, updateStatus));
+    EXPECT_EQ(updateStatus, UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestAlertMetricChanged) {
+    StatsdConfig config;
+    AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+    *config.add_atom_matcher() = whatMatcher;
+
+    CountMetric metric = createCountMetric("VALUE1", whatMatcher.id(), nullopt, {});
+    *config.add_count_metric() = metric;
+
+    Alert alert = createAlert("Alert1", config.count_metric(0).id(), 1, 1);
+    *config.add_alert() = alert;
+    EXPECT_TRUE(initConfig(config));
+
+    UpdateStatus updateStatus = UPDATE_UNKNOWN;
+    EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
+                                           /*replacedMetrics*/ {metric.id()}, updateStatus));
+    EXPECT_EQ(updateStatus, UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestAlertDefinitionChanged) {
+    StatsdConfig config;
+    AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+    *config.add_atom_matcher() = whatMatcher;
+
+    *config.add_count_metric() = createCountMetric("VALUE1", whatMatcher.id(), nullopt, {});
+
+    Alert alert = createAlert("Alert1", config.count_metric(0).id(), 1, 1);
+    *config.add_alert() = alert;
+    EXPECT_TRUE(initConfig(config));
+
+    alert.set_num_buckets(2);
+
+    UpdateStatus updateStatus = UPDATE_UNKNOWN;
+    EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
+                                           /*replacedMetrics*/ {}, updateStatus));
+    EXPECT_EQ(updateStatus, UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestUpdateAlerts) {
+    StatsdConfig config;
+    // Add atom matchers/predicates/metrics. These are mostly needed for initStatsdConfig
+    *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+    *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+    *config.add_predicate() = CreateScreenIsOnPredicate();
+
+    CountMetric countMetric = createCountMetric("COUNT1", config.atom_matcher(0).id(), nullopt, {});
+    int64_t countMetricId = countMetric.id();
+    *config.add_count_metric() = countMetric;
+
+    DurationMetric durationMetric =
+            createDurationMetric("DURATION1", config.predicate(0).id(), nullopt, {});
+    int64_t durationMetricId = durationMetric.id();
+    *config.add_duration_metric() = durationMetric;
+
+    // Add alerts.
+    // Preserved.
+    Alert alert1 = createAlert("Alert1", durationMetricId, /*buckets*/ 1, /*triggerSum*/ 5000);
+    int64_t alert1Id = alert1.id();
+    *config.add_alert() = alert1;
+
+    // Replaced.
+    Alert alert2 = createAlert("Alert2", countMetricId, /*buckets*/ 1, /*triggerSum*/ 2);
+    int64_t alert2Id = alert2.id();
+    *config.add_alert() = alert2;
+
+    // Replaced.
+    Alert alert3 = createAlert("Alert3", durationMetricId, /*buckets*/ 3, /*triggerSum*/ 5000);
+    int64_t alert3Id = alert3.id();
+    *config.add_alert() = alert3;
+
+    // Add Subscriptions.
+    Subscription subscription1 = createSubscription("S1", Subscription::ALERT, alert1Id);
+    *config.add_subscription() = subscription1;
+    Subscription subscription2 = createSubscription("S2", Subscription::ALERT, alert1Id);
+    *config.add_subscription() = subscription2;
+    Subscription subscription3 = createSubscription("S3", Subscription::ALERT, alert2Id);
+    *config.add_subscription() = subscription3;
+
+    EXPECT_TRUE(initConfig(config));
+
+    // Add a duration tracker to the duration metric to ensure durationTrackers are updated
+    // with the proper anomalyTrackers.
+    unique_ptr<LogEvent> event = CreateScreenStateChangedEvent(
+            timeBaseNs + 1, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+    oldMetricProducers[1]->onMatchedLogEvent(0, *event.get());
+
+    // Change the count metric. Causes alert2 to be replaced.
+    config.mutable_count_metric(0)->set_bucket(ONE_DAY);
+    // Change num buckets on alert3, causing replacement.
+    alert3.set_num_buckets(5);
+
+    // New alert.
+    Alert alert4 = createAlert("Alert4", durationMetricId, /*buckets*/ 3, /*triggerSum*/ 10000);
+    int64_t alert4Id = alert4.id();
+
+    // Move subscription2 to be on alert2 and make a new subscription.
+    subscription2.set_rule_id(alert2Id);
+    Subscription subscription4 = createSubscription("S4", Subscription::ALERT, alert2Id);
+
+    // Create the new config. Modify the old one to avoid adding the matchers/predicates.
+    // Add alerts in different order so the map is changed.
+    config.clear_alert();
+    *config.add_alert() = alert4;
+    const int alert4Index = 0;
+    *config.add_alert() = alert3;
+    const int alert3Index = 1;
+    *config.add_alert() = alert1;
+    const int alert1Index = 2;
+    *config.add_alert() = alert2;
+    const int alert2Index = 3;
+
+    // Subscription3 is removed.
+    config.clear_subscription();
+    *config.add_subscription() = subscription4;
+    *config.add_subscription() = subscription2;
+    *config.add_subscription() = subscription1;
+
+    // Output data structures from update metrics. Don't care about the outputs besides
+    // replacedMetrics, but need to do this so that the metrics clear their anomaly trackers.
+    unordered_map<int64_t, int> newMetricProducerMap;
+    vector<sp<MetricProducer>> newMetricProducers;
+    unordered_map<int, vector<int>> conditionToMetricMap;
+    unordered_map<int, vector<int>> trackerToMetricMap;
+    set<int64_t> noReportMetricIds;
+    unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+    unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+    vector<int> metricsWithActivation;
+    set<int64_t> replacedMetrics;
+    EXPECT_TRUE(updateMetrics(
+            key, config, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
+            oldAtomMatchingTrackerMap, oldAtomMatchingTrackerMap, /*replacedMatchers*/ {},
+            oldAtomMatchingTrackers, oldConditionTrackerMap, /*replacedConditions=*/{},
+            oldConditionTrackers, {ConditionState::kUnknown}, /*stateAtomIdMap*/ {},
+            /*allStateGroupMaps=*/{},
+            /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
+            newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
+            activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+            metricsWithActivation, replacedMetrics));
+
+    EXPECT_EQ(replacedMetrics, set<int64_t>({countMetricId}));
+
+    unordered_map<int64_t, int> newAlertTrackerMap;
+    vector<sp<AnomalyTracker>> newAnomalyTrackers;
+    EXPECT_TRUE(updateAlerts(config, newMetricProducerMap, replacedMetrics, oldAlertTrackerMap,
+                             oldAnomalyTrackers, anomalyAlarmMonitor, newMetricProducers,
+                             newAlertTrackerMap, newAnomalyTrackers));
+
+    unordered_map<int64_t, int> expectedAlertMap = {
+            {alert1Id, alert1Index},
+            {alert2Id, alert2Index},
+            {alert3Id, alert3Index},
+            {alert4Id, alert4Index},
+    };
+    EXPECT_THAT(newAlertTrackerMap, ContainerEq(expectedAlertMap));
+
+    // Make sure preserved alerts are the same.
+    ASSERT_EQ(newAnomalyTrackers.size(), 4);
+    EXPECT_EQ(oldAnomalyTrackers[oldAlertTrackerMap.at(alert1Id)],
+              newAnomalyTrackers[newAlertTrackerMap.at(alert1Id)]);
+
+    // Make sure replaced alerts are different.
+    EXPECT_NE(oldAnomalyTrackers[oldAlertTrackerMap.at(alert2Id)],
+              newAnomalyTrackers[newAlertTrackerMap.at(alert2Id)]);
+    EXPECT_NE(oldAnomalyTrackers[oldAlertTrackerMap.at(alert3Id)],
+              newAnomalyTrackers[newAlertTrackerMap.at(alert3Id)]);
+
+    // Verify the alerts have the correct anomaly trackers.
+    ASSERT_EQ(newMetricProducers.size(), 2);
+    EXPECT_THAT(newMetricProducers[0]->mAnomalyTrackers,
+                UnorderedElementsAre(newAnomalyTrackers[alert2Index]));
+    // For durationMetric, make sure the duration trackers get the updated anomalyTrackers.
+    DurationMetricProducer* durationProducer =
+            static_cast<DurationMetricProducer*>(newMetricProducers[1].get());
+    EXPECT_THAT(
+            durationProducer->mAnomalyTrackers,
+            UnorderedElementsAre(newAnomalyTrackers[alert1Index], newAnomalyTrackers[alert3Index],
+                                 newAnomalyTrackers[alert4Index]));
+    ASSERT_EQ(durationProducer->mCurrentSlicedDurationTrackerMap.size(), 1);
+    for (const auto& durationTrackerIt : durationProducer->mCurrentSlicedDurationTrackerMap) {
+        EXPECT_EQ(durationTrackerIt.second->mAnomalyTrackers, durationProducer->mAnomalyTrackers);
+    }
+
+    // Verify alerts have the correct subscriptions. Use subscription id as proxy for equivalency.
+    vector<int64_t> alert1Subscriptions;
+    for (const Subscription& subscription : newAnomalyTrackers[alert1Index]->mSubscriptions) {
+        alert1Subscriptions.push_back(subscription.id());
+    }
+    EXPECT_THAT(alert1Subscriptions, UnorderedElementsAre(subscription1.id()));
+    vector<int64_t> alert2Subscriptions;
+    for (const Subscription& subscription : newAnomalyTrackers[alert2Index]->mSubscriptions) {
+        alert2Subscriptions.push_back(subscription.id());
+    }
+    EXPECT_THAT(alert2Subscriptions, UnorderedElementsAre(subscription2.id(), subscription4.id()));
+    EXPECT_THAT(newAnomalyTrackers[alert3Index]->mSubscriptions, IsEmpty());
+    EXPECT_THAT(newAnomalyTrackers[alert4Index]->mSubscriptions, IsEmpty());
+}
+
+TEST_F(ConfigUpdateTest, TestUpdateAlarms) {
+    StatsdConfig config;
+    // Add alarms.
+    Alarm alarm1 = createAlarm("Alarm1", /*offset*/ 1 * MS_PER_SEC, /*period*/ 50 * MS_PER_SEC);
+    int64_t alarm1Id = alarm1.id();
+    *config.add_alarm() = alarm1;
+
+    Alarm alarm2 = createAlarm("Alarm2", /*offset*/ 1 * MS_PER_SEC, /*period*/ 2000 * MS_PER_SEC);
+    int64_t alarm2Id = alarm2.id();
+    *config.add_alarm() = alarm2;
+
+    Alarm alarm3 = createAlarm("Alarm3", /*offset*/ 10 * MS_PER_SEC, /*period*/ 5000 * MS_PER_SEC);
+    int64_t alarm3Id = alarm3.id();
+    *config.add_alarm() = alarm3;
+
+    // Add Subscriptions.
+    Subscription subscription1 = createSubscription("S1", Subscription::ALARM, alarm1Id);
+    *config.add_subscription() = subscription1;
+    Subscription subscription2 = createSubscription("S2", Subscription::ALARM, alarm1Id);
+    *config.add_subscription() = subscription2;
+    Subscription subscription3 = createSubscription("S3", Subscription::ALARM, alarm2Id);
+    *config.add_subscription() = subscription3;
+
+    EXPECT_TRUE(initConfig(config));
+
+    ASSERT_EQ(oldAlarmTrackers.size(), 3);
+    // Config is created at statsd start time, so just add the offsets.
+    EXPECT_EQ(oldAlarmTrackers[0]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1);
+    EXPECT_EQ(oldAlarmTrackers[1]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1);
+    EXPECT_EQ(oldAlarmTrackers[2]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 10);
+
+    // Change alarm2/alarm3.
+    config.mutable_alarm(1)->set_offset_millis(5 * MS_PER_SEC);
+    config.mutable_alarm(2)->set_period_millis(10000 * MS_PER_SEC);
+
+    // Move subscription2 to be on alarm2 and make a new subscription.
+    config.mutable_subscription(1)->set_rule_id(alarm2Id);
+    Subscription subscription4 = createSubscription("S4", Subscription::ALARM, alarm1Id);
+    *config.add_subscription() = subscription4;
+
+    // Update time is 2 seconds after the base time.
+    int64_t currentTimeNs = timeBaseNs + 2 * NS_PER_SEC;
+    vector<sp<AlarmTracker>> newAlarmTrackers;
+    EXPECT_TRUE(initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+                           newAlarmTrackers));
+
+    ASSERT_EQ(newAlarmTrackers.size(), 3);
+    // Config is updated 2 seconds after statsd start
+    // The offset has passed for alarm1, but not for alarms 2/3.
+    EXPECT_EQ(newAlarmTrackers[0]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1 + 50);
+    EXPECT_EQ(newAlarmTrackers[1]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 5);
+    EXPECT_EQ(newAlarmTrackers[2]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 10);
+
+    // Verify alarms have the correct subscriptions. Use subscription id as proxy for equivalency.
+    vector<int64_t> alarm1Subscriptions;
+    for (const Subscription& subscription : newAlarmTrackers[0]->mSubscriptions) {
+        alarm1Subscriptions.push_back(subscription.id());
+    }
+    EXPECT_THAT(alarm1Subscriptions, UnorderedElementsAre(subscription1.id(), subscription4.id()));
+    vector<int64_t> alarm2Subscriptions;
+    for (const Subscription& subscription : newAlarmTrackers[1]->mSubscriptions) {
+        alarm2Subscriptions.push_back(subscription.id());
+    }
+    EXPECT_THAT(alarm2Subscriptions, UnorderedElementsAre(subscription2.id(), subscription3.id()));
+    EXPECT_THAT(newAlarmTrackers[2]->mSubscriptions, IsEmpty());
+
+    // Verify the alarm monitor is updated accordingly once the old alarms are removed.
+    // Alarm2 fires the earliest.
+    oldAlarmTrackers.clear();
+    EXPECT_EQ(periodicAlarmMonitor->getRegisteredAlarmTimeSec(), timeBaseNs / NS_PER_SEC + 5);
+
+    // Do another update 60 seconds after config creation time, after the offsets of each alarm.
+    currentTimeNs = timeBaseNs + 60 * NS_PER_SEC;
+    newAlarmTrackers.clear();
+    EXPECT_TRUE(initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+                           newAlarmTrackers));
+
+    ASSERT_EQ(newAlarmTrackers.size(), 3);
+    // Config is updated one minute after statsd start.
+    // Two periods have passed for alarm 1, one has passed for alarms2/3.
+    EXPECT_EQ(newAlarmTrackers[0]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1 + 2 * 50);
+    EXPECT_EQ(newAlarmTrackers[1]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 5 + 2000);
+    EXPECT_EQ(newAlarmTrackers[2]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 10 + 10000);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
index 0d0a896..9e2350b 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
@@ -27,6 +27,7 @@
 #include "src/condition/ConditionTracker.h"
 #include "src/matchers/AtomMatchingTracker.h"
 #include "src/metrics/CountMetricProducer.h"
+#include "src/metrics/DurationMetricProducer.h"
 #include "src/metrics/GaugeMetricProducer.h"
 #include "src/metrics/MetricProducer.h"
 #include "src/metrics/ValueMetricProducer.h"
@@ -793,6 +794,93 @@
     EXPECT_FALSE(tracker->IsSimpleCondition());
 }
 
+TEST(MetricsManagerTest, TestCreateAnomalyTrackerInvalidMetric) {
+    Alert alert;
+    alert.set_id(123);
+    alert.set_metric_id(1);
+    alert.set_trigger_if_sum_gt(1);
+    alert.set_num_buckets(1);
+
+    sp<AlarmMonitor> anomalyAlarmMonitor;
+    vector<sp<MetricProducer>> metricProducers;
+    // Pass in empty metric producers, causing an error.
+    EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, {}, metricProducers), nullopt);
+}
+
+TEST(MetricsManagerTest, TestCreateAnomalyTrackerNoThreshold) {
+    int64_t metricId = 1;
+    Alert alert;
+    alert.set_id(123);
+    alert.set_metric_id(metricId);
+    alert.set_num_buckets(1);
+
+    CountMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    vector<sp<MetricProducer>> metricProducers({new CountMetricProducer(
+            kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, 0x0123456789, 0, 0)});
+    sp<AlarmMonitor> anomalyAlarmMonitor;
+    EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, {{1, 0}}, metricProducers), nullopt);
+}
+
+TEST(MetricsManagerTest, TestCreateAnomalyTrackerMissingBuckets) {
+    int64_t metricId = 1;
+    Alert alert;
+    alert.set_id(123);
+    alert.set_metric_id(metricId);
+    alert.set_trigger_if_sum_gt(1);
+
+    CountMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    vector<sp<MetricProducer>> metricProducers({new CountMetricProducer(
+            kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, 0x0123456789, 0, 0)});
+    sp<AlarmMonitor> anomalyAlarmMonitor;
+    EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, {{1, 0}}, metricProducers), nullopt);
+}
+
+TEST(MetricsManagerTest, TestCreateAnomalyTrackerGood) {
+    int64_t metricId = 1;
+    Alert alert;
+    alert.set_id(123);
+    alert.set_metric_id(metricId);
+    alert.set_trigger_if_sum_gt(1);
+    alert.set_num_buckets(1);
+
+    CountMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    vector<sp<MetricProducer>> metricProducers({new CountMetricProducer(
+            kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, 0x0123456789, 0, 0)});
+    sp<AlarmMonitor> anomalyAlarmMonitor;
+    EXPECT_NE(createAnomalyTracker(alert, anomalyAlarmMonitor, {{1, 0}}, metricProducers), nullopt);
+}
+
+TEST(MetricsManagerTest, TestCreateAnomalyTrackerDurationTooLong) {
+    int64_t metricId = 1;
+    Alert alert;
+    alert.set_id(123);
+    alert.set_metric_id(metricId);
+    // Impossible for alert to fire since the time is bigger than bucketSize * numBuckets
+    alert.set_trigger_if_sum_gt(MillisToNano(TimeUnitToBucketSizeInMillis(ONE_MINUTE)) + 1);
+    alert.set_num_buckets(1);
+
+    DurationMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+    FieldMatcher dimensions;
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    vector<sp<MetricProducer>> metricProducers({new DurationMetricProducer(
+            kConfigKey, metric, -1 /*no condition*/, {}, 1 /* start index */, 2 /* stop index */,
+            3 /* stop_all index */, false /*nesting*/, wizard, 0x0123456789, dimensions, 0, 0)});
+    sp<AlarmMonitor> anomalyAlarmMonitor;
+    EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, {{1, 0}}, metricProducers), nullopt);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/core/api/current.txt b/core/api/current.txt
index 16a5f5e..05b57af 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -11718,10 +11718,9 @@
     method public long getFirstInstallTime();
     method public android.graphics.drawable.Drawable getIcon(int);
     method public CharSequence getLabel();
+    method public float getLoadingProgress();
     method public String getName();
-    method public float getProgress();
     method public android.os.UserHandle getUser();
-    method public boolean isLoading();
     method public boolean isStartable();
   }
 
@@ -11762,7 +11761,7 @@
     ctor public LauncherApps.Callback();
     method public abstract void onPackageAdded(String, android.os.UserHandle);
     method public abstract void onPackageChanged(String, android.os.UserHandle);
-    method public void onPackageProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float);
+    method public void onPackageLoadingProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float);
     method public abstract void onPackageRemoved(String, android.os.UserHandle);
     method public abstract void onPackagesAvailable(String[], android.os.UserHandle, boolean);
     method public void onPackagesSuspended(String[], android.os.UserHandle);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index daa5414..18fdc0f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5665,7 +5665,7 @@
     method @NonNull public android.media.tv.tuner.frontend.AtscFrontendSettings.Builder setModulation(int);
   }
 
-  public class DtmbFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+  public final class DtmbFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
     method public int getBandwidthCapability();
     method public int getCodeRateCapability();
     method public int getGuardIntervalCapability();
@@ -5674,7 +5674,7 @@
     method public int getTransmissionModeCapability();
   }
 
-  public class DtmbFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+  public final class DtmbFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
     method @NonNull public static android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder builder();
     method public int getBandwidth();
     method public int getCodeRate();
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 45e9c49..43b7722c 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
@@ -204,6 +206,13 @@
      */
     public ArrayList<IBinder> launchCookies = new ArrayList<>();
 
+    /**
+     * The identifier of the parent task that is created by organizer, otherwise
+     * {@link ActivityTaskManager#INVALID_TASK_ID}.
+     * @hide
+     */
+    public int parentTaskId;
+
     TaskInfo() {
         // Do nothing
     }
@@ -253,6 +262,12 @@
         launchCookies.add(cookie);
     }
 
+    /** @hide */
+    @TestApi
+    public boolean hasParentTask() {
+        return parentTaskId != INVALID_TASK_ID;
+    }
+
     /**
      * Reads the TaskInfo from a parcel.
      */
@@ -283,6 +298,7 @@
         source.readBinderList(launchCookies);
         letterboxActivityBounds = source.readTypedObject(Rect.CREATOR);
         positionInParent = source.readTypedObject(Point.CREATOR);
+        parentTaskId = source.readInt();
     }
 
     /**
@@ -316,6 +332,7 @@
         dest.writeBinderList(launchCookies);
         dest.writeTypedObject(letterboxActivityBounds, flags);
         dest.writeTypedObject(positionInParent, flags);
+        dest.writeInt(parentTaskId);
     }
 
     @Override
@@ -338,6 +355,7 @@
                 + " launchCookies" + launchCookies
                 + " letterboxActivityBounds=" + letterboxActivityBounds
                 + " positionInParent=" + positionInParent
+                + " parentTaskId: " + parentTaskId
                 + "}";
     }
 }
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index c854aba..587e883 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.XmlResourceParser;
-import android.os.Build;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.storage.StorageManager;
@@ -92,7 +91,7 @@
     /**
      * @hide
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+    @UnsupportedAppUsage
     static public native int backupToTar(String packageName, String domain,
             String linkdomain, String rootpath, String path, FullBackupDataOutput output);
 
diff --git a/core/java/android/app/backup/OWNERS b/core/java/android/app/backup/OWNERS
index 9c21e8f..7e7710b 100644
--- a/core/java/android/app/backup/OWNERS
+++ b/core/java/android/app/backup/OWNERS
@@ -1,9 +1,4 @@
-alsutton@google.com
-anniemeng@google.com
-brufino@google.com
-bryanmawhinney@google.com
-ctate@google.com
-jorlow@google.com
-nathch@google.com
-rthakohov@google.com
+# Bug component: 656484
+
+include platform/frameworks/base/services/backup:/OWNERS
 
diff --git a/core/java/android/content/pm/IOnAppsChangedListener.aidl b/core/java/android/content/pm/IOnAppsChangedListener.aidl
index f24ed80..830cbe0 100644
--- a/core/java/android/content/pm/IOnAppsChangedListener.aidl
+++ b/core/java/android/content/pm/IOnAppsChangedListener.aidl
@@ -33,5 +33,5 @@
             in Bundle launcherExtras);
     void onPackagesUnsuspended(in UserHandle user, in String[] packageNames);
     void onShortcutChanged(in UserHandle user, String packageName, in ParceledListSlice shortcuts);
-    void onPackageProgressChanged(in UserHandle user, String packageName, float progress);
+    void onPackageLoadingProgressChanged(in UserHandle user, String packageName, float progress);
 }
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index ead80d0..fd96e85 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -91,16 +91,9 @@
     }
 
     /**
-     * @return whether the package is still loading.
+     * @return Package loading progress, range between [0, 1].
      */
-    public boolean isLoading() {
-        return mInternal.getIncrementalStatesInfo().isLoading();
-    }
-
-    /**
-     * @return Package loading progress
-     */
-    public float getProgress() {
+    public float getLoadingProgress() {
         return mInternal.getIncrementalStatesInfo().getProgress();
     }
 
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 2909d66..c964b4b 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -17,7 +17,6 @@
 package android.content.pm;
 
 import static android.Manifest.permission;
-import static android.app.PendingIntent.FLAG_IMMUTABLE;
 
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
@@ -333,7 +332,7 @@
          * @param user The UserHandle of the profile that generated the change.
          * @param progress The new progress value, between [0, 1].
          */
-        public void onPackageProgressChanged(@NonNull String packageName,
+        public void onPackageLoadingProgressChanged(@NonNull String packageName,
                 @NonNull UserHandle user, float progress) {}
     }
 
@@ -1702,15 +1701,15 @@
             }
         }
 
-        public void onPackageProgressChanged(UserHandle user, String packageName,
+        public void onPackageLoadingProgressChanged(UserHandle user, String packageName,
                 float progress) {
             if (DEBUG) {
-                Log.d(TAG, "onPackageProgressChanged " + user.getIdentifier() + ","
+                Log.d(TAG, "onPackageLoadingProgressChanged " + user.getIdentifier() + ","
                         + packageName + "," + progress);
             }
             synchronized (LauncherApps.this) {
                 for (CallbackMessageHandler callback : mCallbacks) {
-                    callback.postOnPackageProgressChanged(user, packageName, progress);
+                    callback.postOnPackageLoadingProgressChanged(user, packageName, progress);
                 }
             }
         }
@@ -1777,7 +1776,7 @@
                     mCallback.onShortcutsChanged(info.packageName, info.shortcuts, info.user);
                     break;
                 case MSG_LOADING_PROGRESS_CHANGED:
-                    mCallback.onPackageProgressChanged(info.packageName, info.user,
+                    mCallback.onPackageLoadingProgressChanged(info.packageName, info.user,
                             info.mLoadingProgress);
                     break;
             }
@@ -1847,7 +1846,7 @@
             obtainMessage(MSG_SHORTCUT_CHANGED, info).sendToTarget();
         }
 
-        public void postOnPackageProgressChanged(UserHandle user, String packageName,
+        public void postOnPackageLoadingProgressChanged(UserHandle user, String packageName,
                 float progress) {
             CallbackInfo info = new CallbackInfo();
             info.packageName = packageName;
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index e65d7b5..9f322fb 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -419,6 +419,8 @@
      *
      * @see com.android.server.locksettings.LockSettingsService
      *
+     * TODO(b/171335732): should take userId
+     *
      * @hide
      */
     @RequiresPermission(MANAGE_BIOMETRIC)
@@ -426,7 +428,7 @@
         if (mService != null) {
             try {
                 mGenerateChallengeCallback = callback;
-                mService.generateChallenge(mToken, sensorId, mServiceReceiver,
+                mService.generateChallenge(mToken, sensorId, 0 /* userId */, mServiceReceiver,
                         mContext.getOpPackageName());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
@@ -470,13 +472,16 @@
     /**
      * Invalidates the current challenge.
      *
+     * TODO(b/171335732): should take userId and challenge
+     *
      * @hide
      */
     @RequiresPermission(MANAGE_BIOMETRIC)
     public void revokeChallenge(int sensorId) {
         if (mService != null) {
             try {
-                mService.revokeChallenge(mToken, sensorId, mContext.getOpPackageName());
+                mService.revokeChallenge(mToken, sensorId, 0 /* userId */,
+                        mContext.getOpPackageName(), 0 /* challenge */);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index b85b6f7..490c95b 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -32,7 +32,7 @@
     List<FaceSensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);
 
     // Authenticate the given sessionId with a face
-    void authenticate(IBinder token, long operationId, int userid, IFaceServiceReceiver receiver,
+    void authenticate(IBinder token, long operationId, int userId, IFaceServiceReceiver receiver,
             String opPackageName);
 
     // Uses the face hardware to detect for the presence of a face, without giving details
@@ -83,10 +83,10 @@
     boolean isHardwareDetected(String opPackageName);
 
     // Get a pre-enrollment authentication token
-    void generateChallenge(IBinder token, int sensorId, IFaceServiceReceiver receiver, String opPackageName);
+    void generateChallenge(IBinder token, int sensorId, int userId, IFaceServiceReceiver receiver, String opPackageName);
 
     // Finish an enrollment sequence and invalidate the authentication token
-    void revokeChallenge(IBinder token, int sensorId, String opPackageName);
+    void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName, long challenge);
 
     // Determine if a user has at least one enrolled face
     boolean hasEnrolledFaces(int userId, String opPackageName);
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index d2c74e9..4afe4b3 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -766,6 +766,26 @@
     }
 
     /**
+     * Checks if the specified user has enrollments in any of the specified sensors.
+     * @hide
+     */
+    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+    public boolean hasEnrolledTemplatesForAnySensor(int userId,
+            @NonNull List<FingerprintSensorPropertiesInternal> sensors) {
+        if (mService == null) {
+            Slog.w(TAG, "hasEnrolledTemplatesForAnySensor: no fingerprint service");
+            return false;
+        }
+
+        try {
+            return mService.hasEnrolledTemplatesForAnySensor(userId, sensors,
+                    mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * @hide
      */
     @RequiresPermission(USE_BIOMETRIC_INTERNAL)
@@ -778,7 +798,7 @@
         try {
             mService.setUdfpsOverlayController(controller);
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -795,7 +815,7 @@
         try {
             mService.onPointerDown(sensorId, x, y, minor, major);
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -812,7 +832,7 @@
         try {
             mService.onPointerUp(sensorId);
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -885,9 +905,8 @@
             }
             return mService.getSensorPropertiesInternal(mContext.getOpPackageName());
         } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
+            throw e.rethrowFromSystemServer();
         }
-        return new ArrayList<>();
     }
 
     /**
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 547de9d..5b14ef7 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -100,6 +100,9 @@
     // Determine if a user has at least one enrolled fingerprint
     boolean hasEnrolledFingerprints(int userId, String opPackageName);
 
+    // Determine if a user has at least one enrolled fingerprint in any of the specified sensors
+    boolean hasEnrolledTemplatesForAnySensor(int userId, in List<FingerprintSensorPropertiesInternal> sensors, String opPackageName);
+
     // Return the LockoutTracker status for the specified user
     int getLockoutModeForUser(int userId);
 
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index bb2357e..3d1755e 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -213,8 +213,7 @@
                         ic,
                         info,
                         moreArgs.argi1 == 1 /* restarting */,
-                        startInputToken,
-                        moreArgs.argi2 == 1 /* shouldPreRenderIme */);
+                        startInputToken);
                 args.recycle();
                 moreArgs.recycle();
                 return;
@@ -340,14 +339,13 @@
     @Override
     public void startInput(IBinder startInputToken, IInputContext inputContext,
             @InputConnectionInspector.MissingMethodFlags final int missingMethods,
-            EditorInfo attribute, boolean restarting, boolean shouldPreRenderIme) {
+            EditorInfo attribute, boolean restarting) {
         if (mCancellationGroup == null) {
             Log.e(TAG, "startInput must be called after bindInput.");
             mCancellationGroup = new CancellationGroup();
         }
         SomeArgs args = SomeArgs.obtain();
         args.argi1 = restarting ? 1 : 0;
-        args.argi2 = shouldPreRenderIme ? 1 : 0;
         args.argi3 = missingMethods;
         mCaller.executeOrSendMessage(mCaller.obtainMessageOOOOO(DO_START_INPUT, startInputToken,
                 inputContext, attribute, mCancellationGroup, args));
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index d290465..32a8c0a 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -19,7 +19,6 @@
 import static android.graphics.Color.TRANSPARENT;
 import static android.inputmethodservice.InputMethodServiceProto.CANDIDATES_VIEW_STARTED;
 import static android.inputmethodservice.InputMethodServiceProto.CANDIDATES_VISIBILITY;
-import static android.inputmethodservice.InputMethodServiceProto.CAN_PRE_RENDER;
 import static android.inputmethodservice.InputMethodServiceProto.CONFIGURATION;
 import static android.inputmethodservice.InputMethodServiceProto.DECOR_VIEW_VISIBLE;
 import static android.inputmethodservice.InputMethodServiceProto.DECOR_VIEW_WAS_VISIBLE;
@@ -33,7 +32,6 @@
 import static android.inputmethodservice.InputMethodServiceProto.IN_SHOW_WINDOW;
 import static android.inputmethodservice.InputMethodServiceProto.IS_FULLSCREEN;
 import static android.inputmethodservice.InputMethodServiceProto.IS_INPUT_VIEW_SHOWN;
-import static android.inputmethodservice.InputMethodServiceProto.IS_PRE_RENDERED;
 import static android.inputmethodservice.InputMethodServiceProto.InsetsProto.CONTENT_TOP_INSETS;
 import static android.inputmethodservice.InputMethodServiceProto.InsetsProto.TOUCHABLE_INSETS;
 import static android.inputmethodservice.InputMethodServiceProto.InsetsProto.TOUCHABLE_REGION;
@@ -421,10 +419,6 @@
     boolean mDecorViewVisible;
     boolean mDecorViewWasVisible;
     boolean mInShowWindow;
-    // True if pre-rendering of IME views/window is supported.
-    boolean mCanPreRender;
-    // If IME is pre-rendered.
-    boolean mIsPreRendered;
     // IME window visibility.
     // Use (mDecorViewVisible && mWindowVisible) to check if IME is visible to the user.
     boolean mWindowVisible;
@@ -672,10 +666,8 @@
         @Override
         public final void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
                 @NonNull EditorInfo editorInfo, boolean restarting,
-                @NonNull IBinder startInputToken, boolean shouldPreRenderIme) {
+                @NonNull IBinder startInputToken) {
             mPrivOps.reportStartInput(startInputToken);
-            mCanPreRender = shouldPreRenderIme;
-            if (DEBUG) Log.v(TAG, "Will Pre-render IME: " + mCanPreRender);
 
             if (restarting) {
                 restartInput(inputConnection, editorInfo);
@@ -712,22 +704,12 @@
                         + " Use requestHideSelf(int) itself");
                 return;
             }
-            final boolean wasVisible = mIsPreRendered
-                    ? mDecorViewVisible && mWindowVisible : isInputViewShown();
+            final boolean wasVisible = isInputViewShown();
             applyVisibilityInInsetsConsumerIfNecessary(false /* setVisible */);
-            if (mIsPreRendered) {
-                if (DEBUG) {
-                    Log.v(TAG, "Making IME window invisible");
-                }
-                setImeWindowStatus(IME_ACTIVE | IME_INVISIBLE, mBackDisposition);
-                onPreRenderedWindowVisibilityChanged(false /* setVisible */);
-            } else {
-                mShowInputFlags = 0;
-                mShowInputRequested = false;
-                doHideWindow();
-            }
-            final boolean isVisible = mIsPreRendered
-                    ? mDecorViewVisible && mWindowVisible : isInputViewShown();
+            mShowInputFlags = 0;
+            mShowInputRequested = false;
+            doHideWindow();
+            final boolean isVisible = isInputViewShown();
             final boolean visibilityChanged = isVisible != wasVisible;
             if (resultReceiver != null) {
                 resultReceiver.send(visibilityChanged
@@ -766,23 +748,15 @@
                         + " Use requestShowSelf(int) itself");
                 return;
             }
-            final boolean wasVisible = mIsPreRendered
-                    ? mDecorViewVisible && mWindowVisible : isInputViewShown();
+            final boolean wasVisible = isInputViewShown();
             if (dispatchOnShowInputRequested(flags, false)) {
-                if (mIsPreRendered) {
-                    if (DEBUG) {
-                        Log.v(TAG, "Making IME window visible");
-                    }
-                    onPreRenderedWindowVisibilityChanged(true /* setVisible */);
-                } else {
-                    showWindow(true);
-                }
+
+                showWindow(true);
                 applyVisibilityInInsetsConsumerIfNecessary(true /* setVisible */);
             }
             // If user uses hard keyboard, IME button should always be shown.
             setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition);
-            final boolean isVisible = mIsPreRendered
-                    ? mDecorViewVisible && mWindowVisible : isInputViewShown();
+            final boolean isVisible = isInputViewShown();
             final boolean visibilityChanged = isVisible != wasVisible;
             if (resultReceiver != null) {
                 resultReceiver.send(visibilityChanged
@@ -1798,7 +1772,7 @@
      * applied by {@link #updateInputViewShown()}.
      */
     public boolean isInputViewShown() {
-        return mCanPreRender ? mWindowVisible : mIsInputViewShown && mDecorViewVisible;
+        return mDecorViewVisible;
     }
 
     /**
@@ -2151,10 +2125,9 @@
 
         mDecorViewWasVisible = mDecorViewVisible;
         mInShowWindow = true;
-        boolean isPreRenderedAndInvisible = mIsPreRendered && !mWindowVisible;
         final int previousImeWindowStatus =
                 (mDecorViewVisible ? IME_ACTIVE : 0) | (isInputViewShown()
-                        ? (isPreRenderedAndInvisible ? IME_INVISIBLE : IME_VISIBLE) : 0);
+                        ? (!mWindowVisible ? IME_INVISIBLE : IME_VISIBLE) : 0);
         startViews(prepareWindow(showInput));
         final int nextImeWindowStatus = mapToImeWindowStatus();
         if (previousImeWindowStatus != nextImeWindowStatus) {
@@ -2163,14 +2136,7 @@
 
         // compute visibility
         onWindowShown();
-        mIsPreRendered = mCanPreRender;
-        if (mIsPreRendered) {
-            onPreRenderedWindowVisibilityChanged(true /* setVisible */);
-        } else {
-            // Pre-rendering not supported.
-            if (DEBUG) Log.d(TAG, "No pre-rendering supported");
-            mWindowVisible = true;
-        }
+        mWindowVisible = true;
 
         // request draw for the IME surface.
         // When IME is not pre-rendered, this will actually show the IME.
@@ -2178,22 +2144,10 @@
             if (DEBUG) Log.v(TAG, "showWindow: draw decorView!");
             mWindow.show();
         }
-        maybeNotifyPreRendered();
         mDecorViewWasVisible = true;
         mInShowWindow = false;
     }
 
-    /**
-     * Notify {@link android.view.ImeInsetsSourceConsumer} if IME has been pre-rendered
-     * for current EditorInfo, when pre-rendering is enabled.
-     */
-    private void maybeNotifyPreRendered() {
-        if (!mCanPreRender || !mIsPreRendered) {
-            return;
-        }
-        mPrivOps.reportPreRendered(getCurrentInputEditorInfo());
-    }
-
 
     private boolean prepareWindow(boolean showInput) {
         boolean doShowInput = false;
@@ -2237,16 +2191,6 @@
         if (doShowInput) startExtractingText(false);
     }
 
-    private void onPreRenderedWindowVisibilityChanged(boolean setVisible) {
-        mWindowVisible = setVisible;
-        mShowInputFlags = setVisible ? mShowInputFlags : 0;
-        mShowInputRequested = setVisible;
-        mDecorViewVisible = setVisible;
-        if (setVisible) {
-            onWindowShown();
-        }
-    }
-
     /**
      * Applies the IME visibility in {@link android.view.ImeInsetsSourceConsumer}.
      *
@@ -2277,7 +2221,6 @@
 
     public void hideWindow() {
         if (DEBUG) Log.v(TAG, "CALL: hideWindow");
-        mIsPreRendered = false;
         mWindowVisible = false;
         finishViews(false /* finishingInput */);
         if (mDecorViewVisible) {
@@ -2384,32 +2327,6 @@
                 mCandidatesViewStarted = true;
                 onStartCandidatesView(mInputEditorInfo, restarting);
             }
-        } else if (mCanPreRender && mInputEditorInfo != null && mStartedInputConnection != null) {
-            // Pre-render IME views and window when real EditorInfo is available.
-            // pre-render IME window and keep it invisible.
-            if (DEBUG) Log.v(TAG, "Pre-Render IME for " + mInputEditorInfo.fieldName);
-            if (mInShowWindow) {
-                Log.w(TAG, "Re-entrance in to showWindow");
-                return;
-            }
-
-            mDecorViewWasVisible = mDecorViewVisible;
-            mInShowWindow = true;
-            startViews(prepareWindow(true /* showInput */));
-
-            // compute visibility
-            mIsPreRendered = true;
-            onPreRenderedWindowVisibilityChanged(false /* setVisible */);
-
-            // request draw for the IME surface.
-            // When IME is not pre-rendered, this will actually show the IME.
-            if (DEBUG) Log.v(TAG, "showWindow: draw decorView!");
-            mWindow.show();
-            maybeNotifyPreRendered();
-            mDecorViewWasVisible = true;
-            mInShowWindow = false;
-        } else {
-            mIsPreRendered = false;
         }
     }
     
@@ -3309,9 +3226,7 @@
 
     private int mapToImeWindowStatus() {
         return IME_ACTIVE
-                | (isInputViewShown()
-                        ? (mCanPreRender ? (mWindowVisible ? IME_VISIBLE : IME_INVISIBLE)
-                        : IME_VISIBLE) : 0);
+                | (isInputViewShown() ? IME_VISIBLE : 0);
     }
 
     private boolean isAutomotive() {
@@ -3349,8 +3264,6 @@
 
         p.println("  mShowInputRequested=" + mShowInputRequested
                 + " mLastShowInputRequested=" + mLastShowInputRequested
-                + " mCanPreRender=" + mCanPreRender
-                + " mIsPreRendered=" + mIsPreRendered
                 + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
         p.println("  mCandidatesVisibility=" + mCandidatesVisibility
                 + " mFullscreenApplied=" + mFullscreenApplied
@@ -3401,8 +3314,6 @@
         }
         proto.write(SHOW_INPUT_REQUESTED, mShowInputRequested);
         proto.write(LAST_SHOW_INPUT_REQUESTED, mLastShowInputRequested);
-        proto.write(CAN_PRE_RENDER, mCanPreRender);
-        proto.write(IS_PRE_RENDERED, mIsPreRendered);
         proto.write(SHOW_INPUT_FLAGS, mShowInputFlags);
         proto.write(CANDIDATES_VISIBILITY, mCandidatesVisibility);
         proto.write(FULLSCREEN_APPLIED, mFullscreenApplied);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 780c4fa..cc3d92d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9758,6 +9758,14 @@
                 "render_shadows_in_compositor";
 
         /**
+         * If true, submit buffers using blast in ViewRootImpl.
+         * (0 = false, 1 = true)
+         * @hide
+         */
+        public static final String DEVELOPMENT_USE_BLAST_ADAPTER_VR =
+                "use_blast_adapter_vr";
+
+        /**
          * If true, submit buffers using blast in SurfaceView.
          * (0 = false, 1 = true)
          * @hide
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index e4ba87c..f08756a 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -218,6 +218,7 @@
     public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58;
     public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59;
     public static final int KM_ERROR_CANNOT_ATTEST_IDS = -66;
+    public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE = -68;
     public static final int KM_ERROR_DEVICE_LOCKED = -72;
     public static final int KM_ERROR_UNIMPLEMENTED = -100;
     public static final int KM_ERROR_VERSION_MISMATCH = -101;
@@ -265,6 +266,8 @@
         sErrorCodeToString.put(KM_ERROR_INVALID_MAC_LENGTH,
                 "Invalid MAC or authentication tag length");
         sErrorCodeToString.put(KM_ERROR_CANNOT_ATTEST_IDS, "Unable to attest device ids");
+        sErrorCodeToString.put(KM_ERROR_HARDWARE_TYPE_UNAVAILABLE, "Requested security level "
+                        + "(likely Strongbox) is not available.");
         sErrorCodeToString.put(KM_ERROR_DEVICE_LOCKED, "Device locked");
         sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
         sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index dd1a194..5780d4f 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -16,7 +16,6 @@
 
 package android.view;
 
-import static android.view.ImeInsetsSourceConsumerProto.FOCUSED_EDITOR;
 import static android.view.ImeInsetsSourceConsumerProto.INSETS_SOURCE_CONSUMER;
 import static android.view.ImeInsetsSourceConsumerProto.IS_REQUESTED_VISIBLE_AWAITING_CONTROL;
 import static android.view.InsetsController.AnimationType;
@@ -25,16 +24,10 @@
 import android.annotation.Nullable;
 import android.inputmethodservice.InputMethodService;
 import android.os.IBinder;
-import android.os.Parcel;
-import android.text.TextUtils;
 import android.util.proto.ProtoOutputStream;
 import android.view.SurfaceControl.Transaction;
-import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.Arrays;
 import java.util.function.Supplier;
 
 /**
@@ -42,13 +35,6 @@
  * @hide
  */
 public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
-    private EditorInfo mFocusedEditor;
-    private EditorInfo mPreRenderedEditor;
-    /**
-     * Determines if IME would be shown next time IME is pre-rendered for currently focused
-     * editor {@link #mFocusedEditor} if {@link #isServedEditorRendered} is {@code true}.
-     */
-    private boolean mShowOnNextImeRender;
 
     /**
      * Tracks whether we have an outstanding request from the IME to show, but weren't able to
@@ -62,23 +48,6 @@
         super(ITYPE_IME, state, transactionSupplier, controller);
     }
 
-    public void onPreRendered(EditorInfo info) {
-        mPreRenderedEditor = info;
-        if (mShowOnNextImeRender) {
-            mShowOnNextImeRender = false;
-            if (isServedEditorRendered()) {
-                applyImeVisibility(true /* setVisible */);
-            }
-        }
-    }
-
-    public void onServedEditorChanged(EditorInfo info) {
-        if (isFallbackOrEmptyEditor(info)) {
-            mShowOnNextImeRender = false;
-        }
-        mFocusedEditor = info;
-    }
-
     public void applyImeVisibility(boolean setVisible) {
         mController.applyImeVisibility(setVisible);
     }
@@ -170,73 +139,10 @@
         }
     }
 
-    private boolean isFallbackOrEmptyEditor(EditorInfo info) {
-        // TODO(b/123044812): Handle fallback input gracefully in IME Insets API
-        return info == null || (info.fieldId <= 0 && info.inputType <= 0);
-    }
-
-    private boolean isServedEditorRendered() {
-        if (mFocusedEditor == null || mPreRenderedEditor == null
-                || isFallbackOrEmptyEditor(mFocusedEditor)
-                || isFallbackOrEmptyEditor(mPreRenderedEditor)) {
-            // No view is focused or ready.
-            return false;
-        }
-        return areEditorsSimilar(mFocusedEditor, mPreRenderedEditor);
-    }
-
-    @VisibleForTesting
-    public static boolean areEditorsSimilar(EditorInfo info1, EditorInfo info2) {
-        // We don't need to compare EditorInfo.fieldId (View#id) since that shouldn't change
-        // IME views.
-        boolean areOptionsSimilar =
-                info1.imeOptions == info2.imeOptions
-                && info1.inputType == info2.inputType
-                && TextUtils.equals(info1.packageName, info2.packageName);
-        areOptionsSimilar &= info1.privateImeOptions != null
-                ? info1.privateImeOptions.equals(info2.privateImeOptions) : true;
-
-        if (!areOptionsSimilar) {
-            return false;
-        }
-
-        // compare bundle extras.
-        if ((info1.extras == null && info2.extras == null) || info1.extras == info2.extras) {
-            return true;
-        }
-        if ((info1.extras == null && info2.extras != null)
-                || (info1.extras == null && info2.extras != null)) {
-            return false;
-        }
-        if (info1.extras.hashCode() == info2.extras.hashCode()
-                || info1.extras.equals(info1)) {
-            return true;
-        }
-        if (info1.extras.size() != info2.extras.size()) {
-            return false;
-        }
-        if (info1.extras.toString().equals(info2.extras.toString())) {
-            return true;
-        }
-
-        // Compare bytes
-        Parcel parcel1 = Parcel.obtain();
-        info1.extras.writeToParcel(parcel1, 0);
-        parcel1.setDataPosition(0);
-        Parcel parcel2 = Parcel.obtain();
-        info2.extras.writeToParcel(parcel2, 0);
-        parcel2.setDataPosition(0);
-
-        return Arrays.equals(parcel1.createByteArray(), parcel2.createByteArray());
-    }
-
     @Override
     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
         super.dumpDebug(proto, INSETS_SOURCE_CONSUMER);
-        if (mFocusedEditor != null) {
-            mFocusedEditor.dumpDebug(proto, FOCUSED_EDITOR);
-        }
         proto.write(IS_REQUESTED_VISIBLE_AWAITING_CONTROL, mIsRequestedVisibleAwaitingControl);
         proto.end(token);
     }
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 9ea4c93..d37edaa 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -135,6 +135,8 @@
             int blurRadius);
     private static native void nativeSetLayerStack(long transactionObj, long nativeObject,
             int layerStack);
+    private static native void nativeSetBlurRegions(long transactionObj, long nativeObj,
+            float[][] regions, int length);
 
     private static native boolean nativeClearContentFrameStats(long nativeObject);
     private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
@@ -2954,6 +2956,21 @@
         }
 
         /**
+         * Specify what regions should be blurred on the {@link SurfaceControl}.
+         *
+         * @param sc SurfaceControl.
+         * @param regions List of regions that will have blurs.
+         * @return itself.
+         * @see BlurRegion#toFloatArray()
+         * @hide
+         */
+        public Transaction setBlurRegions(SurfaceControl sc, float[][] regions) {
+            checkPreconditions(sc);
+            nativeSetBlurRegions(mNativeObject, sc.mNativeObject, regions, regions.length);
+            return this;
+        }
+
+        /**
          * @hide
          */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.O)
@@ -3482,4 +3499,64 @@
     public static Transaction getGlobalTransaction() {
         return sGlobalTransaction;
     }
+
+    /**
+     * Wrapper for sending blur data to SurfaceFlinger.
+     * @hide
+     */
+    public static final class BlurRegion {
+        public int blurRadius;
+        public float cornerRadiusTL;
+        public float cornerRadiusTR;
+        public float cornerRadiusBL;
+        public float cornerRadiusBR;
+        public float alpha = 1;
+        public boolean visible = true;
+        public final Rect rect = new Rect();
+
+        private final float[] mFloatArray = new float[10];
+
+        public BlurRegion() {
+        }
+
+        public BlurRegion(BlurRegion other) {
+            rect.set(other.rect);
+            blurRadius = other.blurRadius;
+            alpha = other.alpha;
+            cornerRadiusTL = other.cornerRadiusTL;
+            cornerRadiusTR = other.cornerRadiusTR;
+            cornerRadiusBL = other.cornerRadiusBL;
+            cornerRadiusBR = other.cornerRadiusBR;
+        }
+
+        /**
+         * Serializes this class into a float array that's more JNI friendly.
+         */
+        public float[] toFloatArray() {
+            mFloatArray[0] = blurRadius;
+            mFloatArray[1] = alpha;
+            mFloatArray[2] = rect.left;
+            mFloatArray[3] = rect.top;
+            mFloatArray[4] = rect.right;
+            mFloatArray[5] = rect.bottom;
+            mFloatArray[6] = cornerRadiusTL;
+            mFloatArray[7] = cornerRadiusTR;
+            mFloatArray[8] = cornerRadiusBL;
+            mFloatArray[9] = cornerRadiusBR;
+            return mFloatArray;
+        }
+
+        @Override
+        public String toString() {
+            return "BlurRegion{"
+                    + "blurRadius=" + blurRadius
+                    + ", corners={" + cornerRadiusTL
+                    + "," + cornerRadiusTR
+                    + "," + cornerRadiusBL
+                    + "," + cornerRadiusBR
+                    + "}, alpha=" + alpha
+                    + ", rect=" + rect
+                    + "}";
+        }
+    }
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 14ba699..0e8cd54 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -187,6 +187,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.graphics.drawable.BackgroundBlurDrawable;
 import com.android.internal.inputmethod.InputMethodDebug;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.os.SomeArgs;
@@ -654,6 +655,9 @@
 
     private ScrollCaptureConnection mScrollCaptureConnection;
 
+    private final BackgroundBlurDrawable.Aggregator mBlurRegionAggregator =
+            new BackgroundBlurDrawable.Aggregator(this);
+
     /**
      * @return {@link ImeFocusController} for this instance.
      */
@@ -3819,6 +3823,8 @@
     private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler,
             boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) {
         return frameNr -> {
+            mBlurRegionAggregator.dispatchBlurTransactionIfNeeded(frameNr);
+
             // Use a new transaction here since mRtBLASTSyncTransaction can only be accessed by
             // the render thread and mSurfaceChangedTransaction can only be accessed by the UI
             // thread. The temporary transaction is used so mRtBLASTSyncTransaction can be merged
@@ -3849,7 +3855,8 @@
                 .captureFrameCommitCallbacks();
         final boolean needFrameCompleteCallback =
                 mNextDrawUseBLASTSyncTransaction || mReportNextDraw
-                        || (commitCallbacks != null && commitCallbacks.size() > 0);
+                        || (commitCallbacks != null && commitCallbacks.size() > 0)
+                        || mBlurRegionAggregator.hasRegions();
         if (needFrameCompleteCallback) {
             mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(
                     createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw,
@@ -9915,6 +9922,36 @@
         }
     }
 
+    /**
+     * Sends a list of blur regions to SurfaceFlinger, tagged with a frame.
+     *
+     * @param regionCopy List of regions
+     * @param frameNumber Frame where it should be applied (or current when using BLAST)
+     */
+    public void dispatchBlurRegions(float[][] regionCopy, long frameNumber) {
+        final SurfaceControl surfaceControl = getSurfaceControl();
+        if (!surfaceControl.isValid()) {
+            return;
+        }
+        if (useBLAST()) {
+            synchronized (getBlastTransactionLock()) {
+                getBLASTSyncTransaction().setBlurRegions(surfaceControl, regionCopy);
+            }
+        } else {
+            SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+            transaction.setBlurRegions(surfaceControl, regionCopy);
+            transaction.deferTransactionUntil(surfaceControl, getSurfaceControl(), frameNumber);
+            transaction.apply();
+        }
+    }
+
+    /**
+     * Creates a background blur drawable for the backing {@link Surface}.
+     */
+    public BackgroundBlurDrawable createBackgroundBlurDrawable() {
+        return mBlurRegionAggregator.createBackgroundBlurDrawable(mContext);
+    }
+
     SurfaceControl.Transaction getBLASTSyncTransaction() {
         return mRtBLASTSyncTransaction;
     }
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index f44ab3a..de4554b 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -243,7 +243,7 @@
     @MainThread
     default void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
             @NonNull EditorInfo editorInfo, boolean restarting,
-            @NonNull IBinder startInputToken, boolean shouldPreRenderIme) {
+            @NonNull IBinder startInputToken) {
         if (restarting) {
             restartInput(inputConnection, editorInfo);
         } else {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 1931174..6243c63 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -489,7 +489,6 @@
     static final int MSG_TIMEOUT_INPUT_EVENT = 6;
     static final int MSG_FLUSH_INPUT_EVENT = 7;
     static final int MSG_REPORT_FULLSCREEN_MODE = 10;
-    static final int MSG_REPORT_PRE_RENDERED = 15;
     static final int MSG_APPLY_IME_VISIBILITY = 20;
     static final int MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX = 30;
 
@@ -584,17 +583,6 @@
                 mServedConnecting = true;
                 servedView = getServedViewLocked();
             }
-            if (servedView != null && servedView.getHandler() != null) {
-                // Make sure View checks should be on the UI thread.
-                servedView.getHandler().post(() -> {
-                    if (!servedView.onCheckIsTextEditor()) {
-                        // servedView has changed and it's not editable.
-                        synchronized (mH) {
-                            maybeCallServedViewChangedLocked(null);
-                        }
-                    }
-                });
-            }
             return startInputInner(startInputReason,
                     focusedView != null ? focusedView.getWindowToken() : null, startInputFlags,
                     softInputMode, windowFlags);
@@ -919,15 +907,6 @@
                     }
                     return;
                 }
-                case MSG_REPORT_PRE_RENDERED: {
-                    synchronized (mH) {
-                        if (mImeInsetsConsumer != null) {
-                            mImeInsetsConsumer.onPreRendered((EditorInfo) msg.obj);
-                        }
-                    }
-                    return;
-
-                }
                 case MSG_APPLY_IME_VISIBILITY: {
                     synchronized (mH) {
                         if (mImeInsetsConsumer != null) {
@@ -1100,12 +1079,6 @@
         }
 
         @Override
-        public void reportPreRendered(EditorInfo info) {
-            mH.obtainMessage(MSG_REPORT_PRE_RENDERED, 0, 0, info)
-                    .sendToTarget();
-        }
-
-        @Override
         public void applyImeVisibility(boolean setVisible) {
             mH.obtainMessage(MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, 0)
                     .sendToTarget();
@@ -1981,7 +1954,7 @@
 
             // Hook 'em up and let 'er rip.
             mCurrentTextBoxAttribute = tba;
-            maybeCallServedViewChangedLocked(tba);
+
             mServedConnecting = false;
             if (mServedInputConnectionWrapper != null) {
                 mServedInputConnectionWrapper.deactivate();
@@ -3141,12 +3114,6 @@
         }
     }
 
-    private void maybeCallServedViewChangedLocked(EditorInfo tba) {
-        if (mImeInsetsConsumer != null) {
-            mImeInsetsConsumer.onServedEditorChanged(tba);
-        }
-    }
-
     /**
      * <p>This is used for CTS test only. Do not use this method outside of CTS package.<p/>
      * @return the ID of this display which this {@link InputMethodManager} resides
diff --git a/core/java/com/android/internal/BrightnessSynchronizer.java b/core/java/com/android/internal/BrightnessSynchronizer.java
index c98477e..15463cb 100644
--- a/core/java/com/android/internal/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/BrightnessSynchronizer.java
@@ -22,6 +22,7 @@
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.UserHandle;
@@ -55,7 +56,7 @@
 
     private final Queue<Object> mWriteHistory = new LinkedList<>();
 
-    private final Handler mHandler = new Handler() {
+    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -72,7 +73,6 @@
         }
     };
 
-
     public BrightnessSynchronizer(Context context) {
         final BrightnessSyncObserver mBrightnessSyncObserver;
         mContext = context;
diff --git a/core/java/com/android/internal/app/ChooserFlags.java b/core/java/com/android/internal/app/ChooserFlags.java
index 3e26679..1a93f1b 100644
--- a/core/java/com/android/internal/app/ChooserFlags.java
+++ b/core/java/com/android/internal/app/ChooserFlags.java
@@ -33,7 +33,7 @@
      */
     public static final boolean USE_SERVICE_TARGETS_FOR_DIRECT_TARGETS =
             DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
-                SystemUiDeviceConfigFlags.SHARE_USE_SERVICE_TARGETS, true);
+                SystemUiDeviceConfigFlags.SHARE_USE_SERVICE_TARGETS, false);
 
     /**
      * Whether to use {@link AppPredictionManager} to query for direct share targets (as opposed to
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index a2af4d6..777534e 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -430,6 +430,11 @@
     public static final String USE_BACK_GESTURE_ML_MODEL = "use_back_gesture_ml_model";
 
     /**
+     * (string) The name of the ML model for Back Gesture.
+     */
+    public static final String BACK_GESTURE_ML_MODEL_NAME = "back_gesture_ml_model_name";
+
+    /**
      * (float) Threshold for Back Gesture ML model prediction.
      */
     public static final String BACK_GESTURE_ML_MODEL_THRESHOLD = "back_gesture_ml_model_threshold";
diff --git a/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java b/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java
new file mode 100644
index 0000000..6ea9e66
--- /dev/null
+++ b/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.graphics.drawable;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RenderNode;
+import android.graphics.drawable.Drawable;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.view.SurfaceControl;
+import android.view.ViewRootImpl;
+
+import com.android.internal.R;
+
+/**
+ * A drawable that keeps track of a blur region, pokes a hole under it, and propagates its state
+ * to SurfaceFlinger.
+ */
+public final class BackgroundBlurDrawable extends Drawable {
+
+    private static final String TAG = BackgroundBlurDrawable.class.getSimpleName();
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private final Aggregator mAggregator;
+    private final RenderNode mRenderNode;
+    private final Paint mPaint = new Paint();
+    private final Path mRectPath = new Path();
+    private final float[] mTmpRadii = new float[8];
+    private final SurfaceControl.BlurRegion mBlurRegion = new SurfaceControl.BlurRegion();
+
+    // This will be called from a thread pool.
+    private final RenderNode.PositionUpdateListener mPositionUpdateListener =
+            new RenderNode.PositionUpdateListener() {
+            @Override
+            public void positionChanged(long frameNumber, int left, int top, int right,
+                    int bottom) {
+                synchronized (mAggregator) {
+                    mBlurRegion.rect.set(left, top, right, bottom);
+                    mAggregator.onBlurRegionUpdated(BackgroundBlurDrawable.this, mBlurRegion);
+                }
+            }
+
+            @Override
+            public void positionLost(long frameNumber) {
+                synchronized (mAggregator) {
+                    mBlurRegion.rect.setEmpty();
+                    mAggregator.onBlurRegionUpdated(BackgroundBlurDrawable.this, mBlurRegion);
+                }
+            }
+        };
+
+    private BackgroundBlurDrawable(Aggregator aggregator) {
+        mAggregator = aggregator;
+        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+        mRenderNode = new RenderNode("BackgroundBlurDrawable");
+        mRenderNode.addPositionUpdateListener(mPositionUpdateListener);
+    }
+
+    @Override
+    public void draw(@NonNull Canvas canvas) {
+        if (mRectPath.isEmpty() || !isVisible() || getAlpha() == 0) {
+            return;
+        }
+        canvas.drawPath(mRectPath, mPaint);
+        canvas.drawRenderNode(mRenderNode);
+    }
+
+    @Override
+    public boolean setVisible(boolean visible, boolean restart) {
+        boolean changed = super.setVisible(visible, restart);
+        if (changed) {
+            mBlurRegion.visible = visible;
+        }
+        return changed;
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+        mBlurRegion.alpha = alpha / 255f;
+        invalidateSelf();
+    }
+
+    /**
+     * Blur radius in pixels.
+     */
+    public void setBlurRadius(int blurRadius) {
+        mBlurRegion.blurRadius = blurRadius;
+        invalidateSelf();
+    }
+
+    /**
+     * Sets the corner radius, in degrees.
+     */
+    public void setCornerRadius(float cornerRadius) {
+        setCornerRadius(cornerRadius, cornerRadius, cornerRadius, cornerRadius);
+    }
+
+    /**
+     * Sets the corner radius in degrees.
+     * @param cornerRadiusTL top left radius.
+     * @param cornerRadiusTR top right radius.
+     * @param cornerRadiusBL bottom left radius.
+     * @param cornerRadiusBR bottom right radius.
+     */
+    public void setCornerRadius(float cornerRadiusTL, float cornerRadiusTR, float cornerRadiusBL,
+            float cornerRadiusBR) {
+        synchronized (mAggregator) {
+            mBlurRegion.cornerRadiusTL = cornerRadiusTL;
+            mBlurRegion.cornerRadiusTR = cornerRadiusTR;
+            mBlurRegion.cornerRadiusBL = cornerRadiusBL;
+            mBlurRegion.cornerRadiusBR = cornerRadiusBR;
+        }
+        updatePath();
+        invalidateSelf();
+    }
+
+    @Override
+    public void setBounds(int left, int top, int right, int bottom) {
+        super.setBounds(left, top, right, bottom);
+        mRenderNode.setPosition(left, top, right, bottom);
+        updatePath();
+    }
+
+    private void updatePath() {
+        synchronized (mAggregator) {
+            mTmpRadii[0] = mTmpRadii[1] = mBlurRegion.cornerRadiusTL;
+            mTmpRadii[2] = mTmpRadii[3] = mBlurRegion.cornerRadiusTR;
+            mTmpRadii[4] = mTmpRadii[5] = mBlurRegion.cornerRadiusBL;
+            mTmpRadii[6] = mTmpRadii[7] = mBlurRegion.cornerRadiusBR;
+        }
+        mRectPath.reset();
+        if (getAlpha() == 0 || !isVisible()) {
+            return;
+        }
+        Rect bounds = getBounds();
+        mRectPath.addRoundRect(bounds.left, bounds.top, bounds.right, bounds.bottom, mTmpRadii,
+                Path.Direction.CW);
+    }
+
+    @Override
+    public void setColorFilter(@Nullable ColorFilter colorFilter) {
+        throw new IllegalArgumentException("not implemented");
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+
+    /**
+     * Responsible for keeping track of all blur regions of a {@link ViewRootImpl} and posting a
+     * message when it's time to propagate them.
+     */
+    public static final class Aggregator {
+
+        private final ArrayMap<BackgroundBlurDrawable, SurfaceControl.BlurRegion> mBlurRegions =
+                new ArrayMap<>();
+        private final ViewRootImpl mViewRoot;
+        private float[][] mTmpBlurRegionsArray;
+        private boolean mNeedsUpdate;
+
+        public Aggregator(ViewRootImpl viewRoot) {
+            mViewRoot = viewRoot;
+        }
+
+        /**
+         * Creates a blur region with default radius.
+         */
+        public BackgroundBlurDrawable createBackgroundBlurDrawable(Context context) {
+            BackgroundBlurDrawable drawable = new BackgroundBlurDrawable(this);
+            drawable.setBlurRadius(context.getResources().getDimensionPixelSize(
+                    R.dimen.default_background_blur_radius));
+            return drawable;
+        }
+
+        /**
+         * Called from RenderThread only, already locked.
+         * @param drawable
+         * @param blurRegion
+         */
+        void onBlurRegionUpdated(BackgroundBlurDrawable drawable,
+                SurfaceControl.BlurRegion blurRegion) {
+            if (blurRegion.rect.isEmpty() || blurRegion.alpha == 0 || blurRegion.blurRadius == 0
+                    || !blurRegion.visible) {
+                mBlurRegions.remove(drawable);
+                mNeedsUpdate = true;
+                if (DEBUG) {
+                    Log.d(TAG, "Remove " + blurRegion);
+                }
+            } else {
+                mBlurRegions.put(drawable, blurRegion);
+                mNeedsUpdate = true;
+                if (DEBUG) {
+                    Log.d(TAG, "Update " + blurRegion);
+                }
+            }
+        }
+
+        /**
+         * If there are any blur regions visible on the screen at the moment.
+         */
+        public boolean hasRegions() {
+            return mBlurRegions.size() > 0;
+        }
+
+        /**
+         * Dispatch blur updates, if there were any.
+         * @param frameNumber Frame where the update should happen.
+         */
+        public void dispatchBlurTransactionIfNeeded(long frameNumber) {
+            synchronized (this) {
+                if (!mNeedsUpdate) {
+                    return;
+                }
+                mNeedsUpdate = false;
+
+                if (mTmpBlurRegionsArray == null
+                        || mTmpBlurRegionsArray.length != mBlurRegions.size()) {
+                    mTmpBlurRegionsArray = new float[mBlurRegions.size()][];
+                }
+                if (DEBUG) {
+                    Log.d(TAG, "onBlurRegionUpdated will dispatch " + mTmpBlurRegionsArray.length
+                            + " regions for frame " + frameNumber);
+                }
+                for (int i = 0; i < mTmpBlurRegionsArray.length; i++) {
+                    mTmpBlurRegionsArray[i] = mBlurRegions.valueAt(i).toFloatArray();
+                }
+
+                mViewRoot.dispatchBlurRegions(mTmpBlurRegionsArray, frameNumber);
+            }
+        }
+    }
+}
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
index 9a22686..f0e26cf 100644
--- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -17,7 +17,6 @@
 package com.android.internal.inputmethod;
 
 import android.net.Uri;
-import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.internal.inputmethod.IInputContentUriToken;
@@ -40,6 +39,5 @@
     boolean switchToNextInputMethod(boolean onlyCurrentIme);
     boolean shouldOfferSwitchingToNextInputMethod();
     void notifyUserAction();
-    void reportPreRendered(in EditorInfo info);
     void applyImeVisibility(IBinder showOrHideInputToken, boolean setVisible);
 }
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
index 9b1299e..d6730e8 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -24,7 +24,6 @@
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.View;
-import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
 import com.android.internal.annotations.GuardedBy;
@@ -351,24 +350,6 @@
     }
 
     /**
-     * Calls {@link IInputMethodPrivilegedOperations#reportPreRendered(info)}.
-     *
-     * @param info {@link EditorInfo} of the currently rendered {@link TextView}.
-     */
-    @AnyThread
-    public void reportPreRendered(EditorInfo info) {
-        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
-        if (ops == null) {
-            return;
-        }
-        try {
-            ops.reportPreRendered(info);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Calls {@link IInputMethodPrivilegedOperations#applyImeVisibility(IBinder, boolean)}.
      *
      * @param showOrHideInputToken placeholder token that maps to window requesting
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index 40e4f4d..c336373 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -45,7 +45,7 @@
     void unbindInput();
 
     void startInput(in IBinder startInputToken, in IInputContext inputContext, int missingMethods,
-            in EditorInfo attribute, boolean restarting, boolean preRenderImeViews);
+            in EditorInfo attribute, boolean restarting);
 
     void createSession(in InputChannel channel, IInputSessionCallback callback);
 
diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl
index c9443b0..1145f51 100644
--- a/core/java/com/android/internal/view/IInputMethodClient.aidl
+++ b/core/java/com/android/internal/view/IInputMethodClient.aidl
@@ -16,8 +16,6 @@
 
 package com.android.internal.view;
 
-import android.view.inputmethod.EditorInfo;
-
 import com.android.internal.view.InputBindResult;
 
 /**
@@ -30,7 +28,6 @@
     void setActive(boolean active, boolean fullscreen);
     void scheduleStartInputIfNecessary(boolean fullscreen);
     void reportFullscreenMode(boolean fullscreen);
-    void reportPreRendered(in EditorInfo info);
     void applyImeVisibility(boolean setVisible);
     void updateActivityViewToScreenMatrix(int bindSequence, in float[] matrixValues);
     void setImeTraceEnabled(boolean enabled);
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index ce8b599..832c066 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -256,11 +256,13 @@
 }
 
 static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointerCoords,
-        float xOffset, float yOffset, jobject outPointerCoordsObj) {
-    env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x,
-            rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_X) + xOffset);
-    env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y,
-            rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_Y) + yOffset);
+                                    ui::Transform transform, jobject outPointerCoordsObj) {
+    float rawX = rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_X);
+    float rawY = rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_Y);
+    vec2 transformed = transform.transform(rawX, rawY);
+
+    env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x, transformed.x);
+    env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y, transformed.y);
     env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.pressure,
             rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
     env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.size,
@@ -433,8 +435,7 @@
         }
         rawPointerCoords = event->getHistoricalRawPointerCoords(pointerIndex, historyPos);
     }
-    pointerCoordsFromNative(env, rawPointerCoords, event->getXOffset(), event->getYOffset(),
-            outPointerCoordsObj);
+    pointerCoordsFromNative(env, rawPointerCoords, event->getTransform(), outPointerCoordsObj);
 }
 
 static void android_view_MotionEvent_nativeGetPointerProperties(JNIEnv* env, jclass clazz,
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 17ced9f..f1ec85a 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -40,6 +40,7 @@
 #include <private/gui/ComposerService.h>
 #include <stdio.h>
 #include <system/graphics.h>
+#include <ui/BlurRegion.h>
 #include <ui/ConfigStoreTypes.h>
 #include <ui/DeviceProductInfo.h>
 #include <ui/DisplayConfig.h>
@@ -522,6 +523,43 @@
     transaction->setGeometry(ctrl, source, dst, orientation);
 }
 
+static void nativeSetBlurRegions(JNIEnv* env, jclass clazz, jlong transactionObj,
+                                 jlong nativeObject, jobjectArray regions, jint regionsLength) {
+    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+
+    std::vector<BlurRegion> blurRegionVector;
+    const int size = regionsLength;
+    float region[10];
+    for (int i = 0; i < size; i++) {
+        jfloatArray regionArray = (jfloatArray)env->GetObjectArrayElement(regions, i);
+        env->GetFloatArrayRegion(regionArray, 0, 10, region);
+        float blurRadius = region[0];
+        float alpha = region[1];
+        float left = region[2];
+        float top = region[3];
+        float right = region[4];
+        float bottom = region[5];
+        float cornerRadiusTL = region[6];
+        float cornerRadiusTR = region[7];
+        float cornerRadiusBL = region[8];
+        float cornerRadiusBR = region[9];
+
+        blurRegionVector.push_back(BlurRegion{.blurRadius = static_cast<uint32_t>(blurRadius),
+                                              .cornerRadiusTL = cornerRadiusTL,
+                                              .cornerRadiusTR = cornerRadiusTR,
+                                              .cornerRadiusBL = cornerRadiusBL,
+                                              .cornerRadiusBR = cornerRadiusBR,
+                                              .alpha = alpha,
+                                              .left = static_cast<int>(left),
+                                              .top = static_cast<int>(top),
+                                              .right = static_cast<int>(right),
+                                              .bottom = static_cast<int>(bottom)});
+    }
+
+    transaction->setBlurRegions(ctrl, blurRegionVector);
+}
+
 static void nativeSetSize(JNIEnv* env, jclass clazz, jlong transactionObj,
         jlong nativeObject, jint w, jint h) {
     auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -1626,6 +1664,8 @@
             (void*)nativeSetBackgroundBlurRadius },
     {"nativeSetLayerStack", "(JJI)V",
             (void*)nativeSetLayerStack },
+    {"nativeSetBlurRegions", "(JJ[[FI)V",
+            (void*)nativeSetBlurRegions },
     {"nativeSetShadowRadius", "(JJF)V",
             (void*)nativeSetShadowRadius },
     {"nativeSetFrameRate", "(JJFI)V",
diff --git a/core/proto/android/inputmethodservice/inputmethodservice.proto b/core/proto/android/inputmethodservice/inputmethodservice.proto
index 3b4ebb5..e5d1713 100644
--- a/core/proto/android/inputmethodservice/inputmethodservice.proto
+++ b/core/proto/android/inputmethodservice/inputmethodservice.proto
@@ -39,8 +39,8 @@
     optional .android.view.inputmethod.EditorInfoProto input_editor_info = 13;
     optional bool show_input_requested = 14;
     optional bool last_show_input_requested = 15;
-    optional bool can_pre_render = 16;
-    optional bool is_pre_rendered = 17;
+    reserved 16;  // can_pre_render
+    reserved 17;  // is_pre_rendered
     optional int32 show_input_flags = 18;
     optional int32 candidates_visibility = 19;
     optional bool fullscreen_applied = 20;
diff --git a/core/proto/android/view/imeinsetssourceconsumer.proto b/core/proto/android/view/imeinsetssourceconsumer.proto
index 5bee81b..1b9aff9 100644
--- a/core/proto/android/view/imeinsetssourceconsumer.proto
+++ b/core/proto/android/view/imeinsetssourceconsumer.proto
@@ -28,6 +28,6 @@
  */
 message ImeInsetsSourceConsumerProto {
     optional InsetsSourceConsumerProto insets_source_consumer = 1;
-    optional .android.view.inputmethod.EditorInfoProto focused_editor = 2;
+    reserved 2; // focused_editor = 2
     optional bool is_requested_visible_awaiting_control = 3;
 }
\ No newline at end of file
diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml
index ffb9603..bf66e69 100644
--- a/core/res/res/layout/notification_material_action_list.xml
+++ b/core/res/res/layout/notification_material_action_list.xml
@@ -44,6 +44,14 @@
             </com.android.internal.widget.NotificationActionListLayout>
 
             <ImageView
+                android:id="@+id/snooze_button"
+                android:layout_width="48dp"
+                android:layout_height="48dp"
+                android:layout_gravity="center_vertical|end"
+                android:visibility="gone"
+                android:scaleType="centerInside"
+                />
+            <ImageView
                 android:id="@+id/bubble_button"
                 android:layout_width="48dp"
                 android:layout_height="48dp"
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index d0fceb0..393f229b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1129,10 +1129,8 @@
     <string name="capital_off" msgid="7443704171014626777">"DESACTIVADO"</string>
     <string name="checked" msgid="9179896827054513119">"seleccionado"</string>
     <string name="not_checked" msgid="7972320087569023342">"no seleccionado"</string>
-    <!-- no translation found for selected (6614607926197755875) -->
-    <skip />
-    <!-- no translation found for not_selected (410652016565864475) -->
-    <skip />
+    <string name="selected" msgid="6614607926197755875">"seleccionado"</string>
+    <string name="not_selected" msgid="410652016565864475">"no seleccionado"</string>
     <string name="whichApplication" msgid="5432266899591255759">"Completar acción utilizando"</string>
     <string name="whichApplicationNamed" msgid="6969946041713975681">"Completar acción con %1$s"</string>
     <string name="whichApplicationLabel" msgid="7852182961472531728">"Completar acción"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index a3b8f64..f7f6214 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -940,7 +940,7 @@
     <string name="double_tap_toast" msgid="7065519579174882778">"ટિપ: ઝૂમ વધારવા અને ઘટાડવા માટે બે વાર ટેપ કરો."</string>
     <string name="autofill_this_form" msgid="3187132440451621492">"સ્વતઃભરણ"</string>
     <string name="setup_autofill" msgid="5431369130866618567">"સ્વતઃભરણ સેટ કરો"</string>
-    <string name="autofill_window_title" msgid="4379134104008111961">"<xliff:g id="SERVICENAME">%1$s</xliff:g> સાથે આપમેળે ભરો"</string>
+    <string name="autofill_window_title" msgid="4379134104008111961">"<xliff:g id="SERVICENAME">%1$s</xliff:g> સાથે ઑટોમૅટિક રીતે ભરો"</string>
     <string name="autofill_address_name_separator" msgid="8190155636149596125">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3402882515222673691">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="760522655085707045">", "</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 82a27a8..53c92af 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1798,7 +1798,7 @@
     <string name="package_updated_device_owner" msgid="7560272363805506941">"ធ្វើ​បច្ចុប្បន្នភាព​ដោយ​អ្នកគ្រប់គ្រង​របស់​អ្នក"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"លុប​ដោយ​អ្នកគ្រប់គ្រង​របស់​អ្នក"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"យល់ព្រម"</string>
-    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"ដើម្បី​បង្កើនកម្រិត​ថាមពលថ្ម កម្មវិធី​សន្សំថ្ម៖\n\n• បើករចនាប័ទ្មងងឹត\n• បិទ ឬដាក់កំហិតលើ​សកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពល​ជារូបភាពមួយចំនួន និងមុខងារផ្សេងទៀត​ដូចជា “Ok Google” ជាដើម\n\n"<annotation id="url">"ស្វែងយល់​បន្ថែម"</annotation></string>
+    <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"ដើម្បី​បង្កើនកម្រិត​ថាមពលថ្ម មុខងារ​សន្សំ​ថ្ម៖\n\n• បើករចនាប័ទ្មងងឹត\n• បិទ ឬដាក់កំហិតលើ​សកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពល​ជារូបភាពមួយចំនួន និងមុខងារផ្សេងទៀត​ដូចជា “Hey Google” ជាដើម\n\n"<annotation id="url">"ស្វែងយល់​បន្ថែម"</annotation></string>
     <string name="battery_saver_description" msgid="6794188153647295212">"ដើម្បី​បង្កើនកម្រិត​ថាមពលថ្ម មុខងារ​សន្សំថ្ម៖\n\n• បើករចនាប័ទ្មងងឹត\n• បិទ ឬដាក់កំហិតលើ​សកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពលរូបភាពមួយចំនួន និងមុខងារផ្សេងទៀត​ដូចជា “Ok Google” ជាដើម"</string>
     <string name="data_saver_description" msgid="4995164271550590517">"ដើម្បីជួយកាត់បន្ថយការប្រើប្រាស់ទិន្នន័យ កម្មវិធីសន្សំសំចៃទិន្នន័យរារាំងកម្មវិធីមួយចំនួនមិនឲ្យបញ្ជូន ឬទទួលទិន្នន័យនៅផ្ទៃខាងក្រោយទេ។ កម្មវិធីដែលអ្នកកំពុងប្រើនាពេលបច្ចុប្បន្នអាចចូលប្រើប្រាស់​ទិន្នន័យបាន ប៉ុន្តែអាចនឹងមិនញឹកញាប់ដូចមុនទេ។ ឧទាហរណ៍ រូបភាពមិនបង្ហាញទេ លុះត្រាតែអ្នកប៉ះរូបភាពទាំងនោះ។"</string>
     <string name="data_saver_enable_title" msgid="7080620065745260137">"បើកកម្មវិធីសន្សំសំចៃទិន្នន័យ?"</string>
@@ -2007,9 +2007,9 @@
     <string name="notification_feedback_indicator" msgid="663476517711323016">"ផ្ដល់​មតិកែលម្អ"</string>
     <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ការ​ជូនដំណឹង​ព័ត៌មាន​របស់​មុខងារ​ទម្លាប់"</string>
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ថ្ម​អាច​នឹង​អស់ មុនពេល​សាកថ្មធម្មតា"</string>
-    <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"បាន​បើក​ដំណើរការកម្មវិធី​សន្សំ​ថ្ម ដើម្បីបង្កើនកម្រិត​ថាមពល​​ថ្ម"</string>
+    <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"បាន​បើក​ដំណើរការមុខងារ​សន្សំ​ថ្ម ដើម្បីបង្កើនកម្រិត​ថាមពល​​ថ្ម"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"មុខងារ​សន្សំ​ថ្ម"</string>
-    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"កម្មវិធី​សន្សំ​ថ្ម​ត្រូវបានបិទ"</string>
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"មុខងារ​សន្សំ​ថ្ម​ត្រូវបានបិទ"</string>
     <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ទូរសព្ទ​មាន​កម្រិតថ្ម​គ្រប់គ្រាន់​។ មុខងារ​ផ្សេងៗ​មិន​ត្រូវបាន​រឹតបន្តឹងទៀត​ទេ។"</string>
     <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ថេប្លេត​មាន​កម្រិតថ្ម​គ្រប់គ្រាន់​។ មុខងារ​ផ្សេងៗ​មិន​ត្រូវបាន​រឹតបន្តឹងទៀត​ទេ។"</string>
     <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ឧបករណ៍​មាន​កម្រិតថ្ម​គ្រប់គ្រាន់​។ មុខងារ​ផ្សេងៗ​មិន​ត្រូវបាន​រឹតបន្តឹងទៀត​ទេ។"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index db5603c..e39d46d 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1129,10 +1129,8 @@
     <string name="capital_off" msgid="7443704171014626777">"बंद"</string>
     <string name="checked" msgid="9179896827054513119">"तपासले"</string>
     <string name="not_checked" msgid="7972320087569023342">"तपासले नाही"</string>
-    <!-- no translation found for selected (6614607926197755875) -->
-    <skip />
-    <!-- no translation found for not_selected (410652016565864475) -->
-    <skip />
+    <string name="selected" msgid="6614607926197755875">"निवडला"</string>
+    <string name="not_selected" msgid="410652016565864475">"निवडला नाही"</string>
     <string name="whichApplication" msgid="5432266899591255759">"याचा वापर करून क्रिया पूर्ण करा"</string>
     <string name="whichApplicationNamed" msgid="6969946041713975681">"%1$s वापरून क्रिया पूर्ण करा"</string>
     <string name="whichApplicationLabel" msgid="7852182961472531728">"क्रिया पूर्ण झाली"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index b5fd7b2..915e158 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1129,10 +1129,8 @@
     <string name="capital_off" msgid="7443704171014626777">"बन्द"</string>
     <string name="checked" msgid="9179896827054513119">"जाँच गरिएको"</string>
     <string name="not_checked" msgid="7972320087569023342">"जाँच गरिएको छैन"</string>
-    <!-- no translation found for selected (6614607926197755875) -->
-    <skip />
-    <!-- no translation found for not_selected (410652016565864475) -->
-    <skip />
+    <string name="selected" msgid="6614607926197755875">"चयन गरियो"</string>
+    <string name="not_selected" msgid="410652016565864475">"चयन गरिएन"</string>
     <string name="whichApplication" msgid="5432266899591255759">"प्रयोग गरेर कारबाही पुरा गर्नुहोस्"</string>
     <string name="whichApplicationNamed" msgid="6969946041713975681">"निम्न एपको प्रयोग गरी कारबाही पुरा गर्नुहोस्: %1$s"</string>
     <string name="whichApplicationLabel" msgid="7852182961472531728">"पूर्ण कारबाही"</string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 7eff3d7..544be54e 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -858,6 +858,7 @@
     <dimen name="waterfall_display_right_edge_size">0px</dimen>
     <dimen name="waterfall_display_bottom_edge_size">0px</dimen>
 
+    <dimen name="default_background_blur_radius">100dp</dimen>
     <!-- The maximum height of a thumbnail in a ThumbnailTemplate. The image will be reduced to that height in case they are bigger. -->
     <dimen name="controls_thumbnail_image_max_height">140dp</dimen>
     <!-- The maximum width of a thumbnail in a ThumbnailTemplate. The image will be reduced to that width in case they are bigger.-->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e4a4e20..a294c9d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3553,6 +3553,7 @@
   <java-symbol type="id" name="clip_to_padding_tag" />
   <java-symbol type="id" name="clip_children_tag" />
   <java-symbol type="id" name="bubble_button" />
+  <java-symbol type="id" name="snooze_button" />
   <java-symbol type="dimen" name="bubble_visible_padding_end" />
   <java-symbol type="dimen" name="bubble_gone_padding_end" />
   <java-symbol type="dimen" name="text_size_body_2_material" />
@@ -4078,6 +4079,7 @@
   <java-symbol type="integer" name="config_defaultBinderHeavyHitterAutoSamplerBatchSize" />
   <java-symbol type="dimen" name="config_defaultBinderHeavyHitterAutoSamplerThreshold" />
 
+  <java-symbol type="dimen" name="default_background_blur_radius" />
   <java-symbol type="array" name="config_keep_warming_services" />
   <java-symbol type="string" name="config_display_features" />
   <java-symbol type="array" name="config_internalFoldedPhysicalDisplayIds" />
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
index ac2d4b5..2f2bef8 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
@@ -30,7 +30,7 @@
                 // Score and Property are mixed into the middle to make sure DocumentBuilder's
                 // methods can be interleaved with EmailBuilder's methods.
                 .setScore(1)
-                .setProperty("propertyKey", "propertyValue1", "propertyValue2")
+                .setPropertyString("propertyKey", "propertyValue1", "propertyValue2")
                 .setSubject("subject")
                 .setBody("EmailBody")
                 .build();
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
index 1f2c12b..9c29943 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
@@ -39,22 +39,22 @@
         GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
                 .setTtlMillis(1L)
-                .setProperty("longKey1", 1L, 2L, 3L)
-                .setProperty("doubleKey1", 1.0, 2.0, 3.0)
-                .setProperty("booleanKey1", true, false, true)
-                .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
-                .setProperty("byteKey1", sByteArray1, sByteArray2)
-                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
+                .setPropertyLong("longKey1", 1L, 2L, 3L)
+                .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+                .setPropertyBoolean("booleanKey1", true, false, true)
+                .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
+                .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+                .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
                 .build();
         GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
                 .setTtlMillis(1L)
-                .setProperty("longKey1", 1L, 2L, 3L)
-                .setProperty("doubleKey1", 1.0, 2.0, 3.0)
-                .setProperty("booleanKey1", true, false, true)
-                .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
-                .setProperty("byteKey1", sByteArray1, sByteArray2)
-                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
+                .setPropertyLong("longKey1", 1L, 2L, 3L)
+                .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+                .setPropertyBoolean("booleanKey1", true, false, true)
+                .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
+                .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+                .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
                 .build();
         assertThat(document1).isEqualTo(document2);
         assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
@@ -64,23 +64,23 @@
     public void testDocumentEquals_DifferentOrder() {
         GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
-                .setProperty("longKey1", 1L, 2L, 3L)
-                .setProperty("byteKey1", sByteArray1, sByteArray2)
-                .setProperty("doubleKey1", 1.0, 2.0, 3.0)
-                .setProperty("booleanKey1", true, false, true)
-                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
-                .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
+                .setPropertyLong("longKey1", 1L, 2L, 3L)
+                .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+                .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+                .setPropertyBoolean("booleanKey1", true, false, true)
+                .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
+                .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
                 .build();
 
         // Create second document with same parameter but different order.
         GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
-                .setProperty("booleanKey1", true, false, true)
-                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
-                .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
-                .setProperty("doubleKey1", 1.0, 2.0, 3.0)
-                .setProperty("byteKey1", sByteArray1, sByteArray2)
-                .setProperty("longKey1", 1L, 2L, 3L)
+                .setPropertyBoolean("booleanKey1", true, false, true)
+                .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
+                .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
+                .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+                .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+                .setPropertyLong("longKey1", 1L, 2L, 3L)
                 .build();
         assertThat(document1).isEqualTo(document2);
         assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
@@ -90,13 +90,13 @@
     public void testDocumentEquals_Failure() {
         GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
-                .setProperty("longKey1", 1L, 2L, 3L)
+                .setPropertyLong("longKey1", 1L, 2L, 3L)
                 .build();
 
         // Create second document with same order but different value.
         GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
-                .setProperty("longKey1", 1L, 2L, 4L) // Different
+                .setPropertyLong("longKey1", 1L, 2L, 4L) // Different
                 .build();
         assertThat(document1).isNotEqualTo(document2);
         assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
@@ -106,13 +106,13 @@
     public void testDocumentEquals_Failure_RepeatedFieldOrder() {
         GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
-                .setProperty("booleanKey1", true, false, true)
+                .setPropertyBoolean("booleanKey1", true, false, true)
                 .build();
 
         // Create second document with same order but different value.
         GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
-                .setProperty("booleanKey1", true, true, false) // Different
+                .setPropertyBoolean("booleanKey1", true, true, false) // Different
                 .build();
         assertThat(document1).isNotEqualTo(document2);
         assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
@@ -124,12 +124,12 @@
                 .setCreationTimestampMillis(5L)
                 .setScore(1)
                 .setTtlMillis(1L)
-                .setProperty("longKey1", 1L)
-                .setProperty("doubleKey1", 1.0)
-                .setProperty("booleanKey1", true)
-                .setProperty("stringKey1", "test-value1")
-                .setProperty("byteKey1", sByteArray1)
-                .setProperty("documentKey1", sDocumentProperties1)
+                .setPropertyLong("longKey1", 1L)
+                .setPropertyDouble("doubleKey1", 1.0)
+                .setPropertyBoolean("booleanKey1", true)
+                .setPropertyString("stringKey1", "test-value1")
+                .setPropertyBytes("byteKey1", sByteArray1)
+                .setPropertyDocument("documentKey1", sDocumentProperties1)
                 .build();
         assertThat(document.getUri()).isEqualTo("uri1");
         assertThat(document.getTtlMillis()).isEqualTo(1L);
@@ -149,12 +149,12 @@
     public void testDocumentGetArrayValues() {
         GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
-                .setProperty("longKey1", 1L, 2L, 3L)
-                .setProperty("doubleKey1", 1.0, 2.0, 3.0)
-                .setProperty("booleanKey1", true, false, true)
-                .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
-                .setProperty("byteKey1", sByteArray1, sByteArray2)
-                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
+                .setPropertyLong("longKey1", 1L, 2L, 3L)
+                .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+                .setPropertyBoolean("booleanKey1", true, false, true)
+                .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
+                .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+                .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
                 .build();
 
         assertThat(document.getUri()).isEqualTo("uri1");
@@ -176,12 +176,12 @@
     public void testDocument_ToString() throws Exception {
         GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1")
                 .setCreationTimestampMillis(5L)
-                .setProperty("longKey1", 1L, 2L, 3L)
-                .setProperty("doubleKey1", 1.0, 2.0, 3.0)
-                .setProperty("booleanKey1", true, false, true)
-                .setProperty("stringKey1", "String1", "String2", "String3")
-                .setProperty("byteKey1", sByteArray1, sByteArray2)
-                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
+                .setPropertyLong("longKey1", 1L, 2L, 3L)
+                .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+                .setPropertyBoolean("booleanKey1", true, false, true)
+                .setPropertyString("stringKey1", "String1", "String2", "String3")
+                .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+                .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
                 .build();
         String exceptedString = "{ key: 'creationTimestampMillis' value: 5 } "
                 + "{ key: 'namespace' value:  } "
@@ -219,9 +219,9 @@
     public void testDocumentGetValues_DifferentTypes() {
         GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1")
                 .setScore(1)
-                .setProperty("longKey1", 1L)
-                .setProperty("booleanKey1", true, false, true)
-                .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
+                .setPropertyLong("longKey1", 1L)
+                .setPropertyBoolean("booleanKey1", true, false, true)
+                .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
                 .build();
 
         // Get a value for a key that doesn't exist
@@ -246,6 +246,7 @@
     public void testDocumentInvalid() {
         GenericDocument.Builder builder = new GenericDocument.Builder("uri1", "schemaType1");
         expectThrows(
-                IllegalArgumentException.class, () -> builder.setProperty("test", new boolean[]{}));
+                IllegalArgumentException.class,
+                () -> builder.setPropertyBoolean("test", new boolean[]{}));
     }
 }
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java
deleted file mode 100644
index acbf11a..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2020 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.app.appsearch;
-
-import static org.testng.Assert.expectThrows;
-
-import org.junit.Test;
-
-public class SearchResultsTest {
-    @Test
-    public void buildSearchSpecWithoutTermMatchType() {
-        expectThrows(RuntimeException.class, () -> new SearchSpec.Builder()
-                .setSchemaTypes("testSchemaType")
-                .build());
-    }
-}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java
new file mode 100644
index 0000000..d4635fd
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2020 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.app.appsearch;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.expectThrows;
+
+import android.os.Bundle;
+
+import org.junit.Test;
+
+public class SearchSpecTest {
+    @Test
+    public void buildSearchSpecWithoutTermMatchType() {
+        expectThrows(RuntimeException.class, () -> new SearchSpec.Builder()
+                .addSchema("testSchemaType")
+                .build());
+    }
+
+    @Test
+    public void testBuildSearchSpec() {
+        SearchSpec searchSpec = new SearchSpec.Builder()
+                .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+                .addNamespace("namespace1", "namespace2")
+                .addSchema("schemaTypes1", "schemaTypes2")
+                .setSnippetCount(5)
+                .setSnippetCountPerProperty(10)
+                .setMaxSnippetSize(15)
+                .setNumPerPage(42)
+                .setOrder(SearchSpec.ORDER_ASCENDING)
+                .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE)
+                .build();
+
+        assertThat(searchSpec.getTermMatch()).isEqualTo(SearchSpec.TERM_MATCH_PREFIX);
+        assertThat(searchSpec.getNamespaces())
+                .containsExactly("namespace1", "namespace2").inOrder();
+        assertThat(searchSpec.getSchemas())
+                .containsExactly("schemaTypes1", "schemaTypes2").inOrder();
+        assertThat(searchSpec.getSnippetCount()).isEqualTo(5);
+        assertThat(searchSpec.getSnippetCountPerProperty()).isEqualTo(10);
+        assertThat(searchSpec.getMaxSnippetSize()).isEqualTo(15);
+        assertThat(searchSpec.getNumPerPage()).isEqualTo(42);
+        assertThat(searchSpec.getOrder()).isEqualTo(SearchSpec.ORDER_ASCENDING);
+        assertThat(searchSpec.getRankingStrategy())
+                .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE);
+    }
+
+    @Test
+    public void testGetBundle() {
+        SearchSpec searchSpec = new SearchSpec.Builder()
+                .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+                .addNamespace("namespace1", "namespace2")
+                .addSchema("schemaTypes1", "schemaTypes2")
+                .setSnippetCount(5)
+                .setSnippetCountPerProperty(10)
+                .setMaxSnippetSize(15)
+                .setNumPerPage(42)
+                .setOrder(SearchSpec.ORDER_ASCENDING)
+                .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE)
+                .build();
+
+        Bundle bundle = searchSpec.getBundle();
+        assertThat(bundle.getInt(SearchSpec.TERM_MATCH_TYPE_FIELD))
+                .isEqualTo(SearchSpec.TERM_MATCH_PREFIX);
+        assertThat(bundle.getStringArrayList(SearchSpec.NAMESPACE_FIELD)).containsExactly(
+                "namespace1", "namespace2");
+        assertThat(bundle.getStringArrayList(SearchSpec.SCHEMA_TYPE_FIELD)).containsExactly(
+                "schemaTypes1", "schemaTypes2");
+        assertThat(bundle.getInt(SearchSpec.SNIPPET_COUNT_FIELD)).isEqualTo(5);
+        assertThat(bundle.getInt(SearchSpec.SNIPPET_COUNT_PER_PROPERTY_FIELD)).isEqualTo(10);
+        assertThat(bundle.getInt(SearchSpec.MAX_SNIPPET_FIELD)).isEqualTo(15);
+        assertThat(bundle.getInt(SearchSpec.NUM_PER_PAGE_FIELD)).isEqualTo(42);
+        assertThat(bundle.getInt(SearchSpec.ORDER_FIELD)).isEqualTo(SearchSpec.ORDER_ASCENDING);
+        assertThat(bundle.getInt(SearchSpec.RANKING_STRATEGY_FIELD))
+                .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE);
+    }
+}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java
index 2c7c35f..d56d0c3 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java
@@ -46,12 +46,12 @@
         CustomerDocument customerDocument = new CustomerDocument.Builder("uri1")
                 .setScore(1)
                 .setCreationTimestampMillis(0)
-                .setProperty("longKey1", 1L, 2L, 3L)
-                .setProperty("doubleKey1", 1.0, 2.0, 3.0)
-                .setProperty("booleanKey1", true, false, true)
-                .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
-                .setProperty("byteKey1", sByteArray1, sByteArray2)
-                .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
+                .setPropertyLong("longKey1", 1L, 2L, 3L)
+                .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+                .setPropertyBoolean("booleanKey1", true, false, true)
+                .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
+                .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+                .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
                 .build();
 
         assertThat(customerDocument.getUri()).isEqualTo("uri1");
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index a5b7c61..db838e8 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -17,7 +17,6 @@
 package android.view;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.view.ImeInsetsSourceConsumer.areEditorsSimilar;
 import static android.view.InsetsState.ITYPE_IME;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -33,11 +32,9 @@
 import android.graphics.Insets;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.os.Bundle;
 import android.platform.test.annotations.Presubmit;
 import android.view.WindowManager.BadTokenException;
 import android.view.WindowManager.LayoutParams;
-import android.view.inputmethod.EditorInfo;
 import android.widget.TextView;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -50,8 +47,6 @@
 import org.mockito.Mockito;
 import org.mockito.Spy;
 
-import java.util.ArrayList;
-
 /**
  * Test {@link InsetsSourceConsumer} with IME type.
  *
@@ -133,50 +128,4 @@
                     eq(WindowInsets.Type.ime()), eq(false) /* show */, eq(true) /* fromIme */);
         });
     }
-
-    @Test
-    public void testAreEditorsSimilar() {
-        EditorInfo info1 = new EditorInfo();
-        info1.privateImeOptions = "dummy";
-        EditorInfo info2 = new EditorInfo();
-
-        assertFalse(areEditorsSimilar(info1, info2));
-
-        info1.privateImeOptions = null;
-        assertTrue(areEditorsSimilar(info1, info2));
-
-        info1.inputType = info2.inputType = 3;
-        info1.imeOptions = info2.imeOptions = 0x4;
-        info1.packageName = info2.packageName = "dummy.package";
-        assertTrue(areEditorsSimilar(info1, info2));
-
-        Bundle extras1 = new Bundle();
-        extras1.putByteArray("key1", "value1".getBytes());
-        extras1.putChar("key2", 'c');
-        Bundle extras2 = new Bundle();
-        extras2.putByteArray("key1", "value1".getBytes());
-        extras2.putChar("key2", 'c');
-        info1.extras = extras1;
-        info2.extras = extras2;
-        assertTrue(areEditorsSimilar(info1, info2));
-
-        Bundle extraBundle = new Bundle();
-        ArrayList<Integer> list = new ArrayList<>();
-        list.add(2);
-        list.add(5);
-        extraBundle.putByteArray("key1", "value1".getBytes());
-        extraBundle.putChar("key2", 'c');
-        extraBundle.putIntegerArrayList("key3", list);
-
-        extras1.putAll(extraBundle);
-        extras2.putAll(extraBundle);
-        assertTrue(areEditorsSimilar(info1, info2));
-
-        extras2.putChar("key2", 'd');
-        assertFalse(areEditorsSimilar(info1, info2));
-
-        extras2.putChar("key2", 'c');
-        extras2.putInt("key4", 1);
-        assertFalse(areEditorsSimilar(info1, info2));
-    }
 }
diff --git a/core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java b/core/tests/coretests/src/android/widget/TextViewOnReceiveContentTest.java
similarity index 98%
rename from core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java
rename to core/tests/coretests/src/android/widget/TextViewOnReceiveContentTest.java
index ef659af6..8efd3b4 100644
--- a/core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewOnReceiveContentTest.java
@@ -63,12 +63,12 @@
 
 /**
  * Tests for {@link TextViewOnReceiveContentCallback}. Most of the test cases are in the CTS test
- * {@link android.widget.cts.TextViewOnReceiveContentCallbackTest}. This class tests some internal
+ * {@link android.widget.cts.TextViewOnReceiveContentTest}. This class tests some internal
  * implementation details, e.g. fallback to the keyboard image API.
  */
 @MediumTest
 @RunWith(AndroidJUnit4.class)
-public class TextViewOnReceiveContentCallbackTest {
+public class TextViewOnReceiveContentTest {
     private static final Uri SAMPLE_CONTENT_URI = Uri.parse("content://com.example/path");
 
     @Rule
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 8f5982c..7abcfdc 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -49,18 +49,38 @@
 
     public static final String INSTALL_AS_USER_ACTION = "android.credentials.INSTALL_AS_USER";
 
-    /** Key prefix for CA certificates. */
+    /**
+     * Key prefix for CA certificates.
+     *
+     * @deprecated Keystore no longer supports unstructured blobs. Public certificates are
+     *             stored in typed slots associated with a given alias.
+     */
+    @Deprecated
     public static final String CA_CERTIFICATE = "CACERT_";
 
-    /** Key prefix for user certificates. */
+    /**
+     * Key prefix for user certificates.
+     *
+     * @deprecated Keystore no longer supports unstructured blobs. Public certificates are
+     *             stored in typed slots associated with a given alias.
+     */
+    @Deprecated
     public static final String USER_CERTIFICATE = "USRCERT_";
 
-    /** Key prefix for user private and secret keys. */
+    /**
+     * Key prefix for user private and secret keys.
+     *
+     * @deprecated Keystore no longer uses alias prefixes to discriminate between entry types.
+     */
+    @Deprecated
     public static final String USER_PRIVATE_KEY = "USRPKEY_";
 
-    /** Key prefix for user secret keys.
-     *  @deprecated use {@code USER_PRIVATE_KEY} for this category instead.
+    /**
+     * Key prefix for user secret keys.
+     *
+     * @deprecated use {@code USER_PRIVATE_KEY} for this category instead.
      */
+    @Deprecated
     public static final String USER_SECRET_KEY = "USRSKEY_";
 
     /** Key prefix for VPN. */
@@ -72,7 +92,13 @@
     /** Key prefix for WIFI. */
     public static final String WIFI = "WIFI_";
 
-    /** Key prefix for App Source certificates. */
+    /**
+     * Key prefix for App Source certificates.
+     *
+     * @deprecated This was intended for FS-verity but never used. FS-verity is not
+     *             going to use this constant moving forward.
+     */
+    @Deprecated
     public static final String APP_SOURCE_CERTIFICATE = "FSV_";
 
     /** Key containing suffix of lockdown VPN profile. */
@@ -150,6 +176,7 @@
         pw.close();
         return bao.toByteArray();
     }
+
     /**
      * Convert objects from PEM format, which is used for
      * CA_CERTIFICATE and USER_CERTIFICATE entries.
@@ -167,7 +194,8 @@
             PemObject o;
             while ((o = pr.readPemObject()) != null) {
                 if (o.getType().equals("CERTIFICATE")) {
-                    Certificate c = cf.generateCertificate(new ByteArrayInputStream(o.getContent()));
+                    Certificate c = cf.generateCertificate(
+                            new ByteArrayInputStream(o.getContent()));
                     result.add((X509Certificate) c);
                 } else {
                     throw new IllegalArgumentException("Unknown type " + o.getType());
diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java
index d5b34c4..1c1c2ee 100644
--- a/keystore/java/android/security/KeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/KeyPairGeneratorSpec.java
@@ -16,9 +16,9 @@
 
 package android.security;
 
-import android.app.KeyguardManager;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.KeyguardManager;
 import android.content.Context;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
@@ -78,8 +78,6 @@
 
     private final Date mEndDate;
 
-    private final int mFlags;
-
     /**
      * Parameter specification for the "{@code AndroidKeyPairGenerator}"
      * instance of the {@link java.security.KeyPairGenerator} API. The
@@ -144,7 +142,6 @@
         mSerialNumber = serialNumber;
         mStartDate = startDate;
         mEndDate = endDate;
-        mFlags = flags;
     }
 
     /**
@@ -229,7 +226,7 @@
      * @hide
      */
     public int getFlags() {
-        return mFlags;
+        return 0;
     }
 
     /**
@@ -243,9 +240,15 @@
      * screen after boot.
      *
      * @see KeyguardManager#isDeviceSecure()
+     *
+     * @deprecated Encryption at rest is on by default. If extra binding to the lockscreen screen
+     *             credential is desired use
+     *             {@link KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)}.
+     *             This flag will be ignored from Android S.
      */
+    @Deprecated
     public boolean isEncryptionRequired() {
-        return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0;
+        return false;
     }
 
     /**
@@ -292,8 +295,6 @@
 
         private Date mEndDate;
 
-        private int mFlags;
-
         /**
          * Creates a new instance of the {@code Builder} with the given
          * {@code context}. The {@code context} passed in may be used to pop up
@@ -431,10 +432,15 @@
          * secure lock screen after boot.
          *
          * @see KeyguardManager#isDeviceSecure()
+         *
+         * @deprecated Data at rest encryption is enabled by default. If extra binding to the
+         *             lockscreen credential is desired, use
+         *             {@link KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)}.
+         *             This flag will be ignored from Android S.
          */
         @NonNull
+        @Deprecated
         public Builder setEncryptionRequired() {
-            mFlags |= KeyStore.FLAG_ENCRYPTED;
             return this;
         }
 
@@ -455,7 +461,7 @@
                     mSerialNumber,
                     mStartDate,
                     mEndDate,
-                    mFlags);
+                    0);
         }
     }
 }
diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java
index 66c87ed..51d29b1 100644
--- a/keystore/java/android/security/KeyStoreParameter.java
+++ b/keystore/java/android/security/KeyStoreParameter.java
@@ -48,18 +48,16 @@
  */
 @Deprecated
 public final class KeyStoreParameter implements ProtectionParameter {
-    private final int mFlags;
 
     private KeyStoreParameter(
             int flags) {
-        mFlags = flags;
     }
 
     /**
      * @hide
      */
     public int getFlags() {
-        return mFlags;
+        return 0;
     }
 
     /**
@@ -74,9 +72,16 @@
      * screen after boot.
      *
      * @see KeyguardManager#isDeviceSecure()
+     *
+     * @deprecated Data at rest encryption is enabled by default. If extra binding to the
+     *             lockscreen credential is desired, use
+     *             {@link android.security.keystore.KeyGenParameterSpec
+     *             .Builder#setUserAuthenticationRequired(boolean)}.
+     *             This flag will be ignored from Android S.
      */
+    @Deprecated
     public boolean isEncryptionRequired() {
-        return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0;
+        return false;
     }
 
     /**
@@ -100,7 +105,6 @@
      */
     @Deprecated
     public final static class Builder {
-        private int mFlags;
 
         /**
          * Creates a new instance of the {@code Builder} with the given
@@ -126,14 +130,15 @@
          * the user unlocks the secure lock screen after boot.
          *
          * @see KeyguardManager#isDeviceSecure()
+         *
+         * @deprecated Data at rest encryption is enabled by default. If extra binding to the
+         *             lockscreen credential is desired, use
+         *             {@link android.security.keystore.KeyGenParameterSpec
+         *             .Builder#setUserAuthenticationRequired(boolean)}.
+         *             This flag will be ignored from Android S.
          */
         @NonNull
         public Builder setEncryptionRequired(boolean required) {
-            if (required) {
-                mFlags |= KeyStore.FLAG_ENCRYPTED;
-            } else {
-                mFlags &= ~KeyStore.FLAG_ENCRYPTED;
-            }
             return this;
         }
 
@@ -145,8 +150,7 @@
          */
         @NonNull
         public KeyStoreParameter build() {
-            return new KeyStoreParameter(
-                    mFlags);
+            return new KeyStoreParameter(0 /* flags */);
         }
     }
 }
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 1d85e9f..b87a642 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -57,6 +57,9 @@
     <dimen name="pip_resize_handle_margin">4dp</dimen>
     <dimen name="pip_resize_handle_padding">0dp</dimen>
 
+    <!-- PIP stash offset size, which is the width of visible PIP region when stashed. -->
+    <dimen name="pip_stash_offset">32dp</dimen>
+
     <dimen name="dismiss_target_x_size">24dp</dimen>
     <dimen name="floating_dismiss_bottom_margin">50dp</dimen>
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index d4ff275..51ddb17 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -335,6 +335,12 @@
         listener = mTaskListeners.get(taskId);
         if (listener != null) return listener;
 
+        // Next priority goes to the listener listening to its parent.
+        if (runningTaskInfo.hasParentTask()) {
+            listener = mTaskListeners.get(runningTaskInfo.parentTaskId);
+            if (listener != null) return listener;
+        }
+
         // Next we try type specific listeners.
         final int taskListenerType = taskInfoToTaskListenerType(runningTaskInfo);
         return mTaskListeners.get(taskListenerType);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
index d0ab31d..fc523aef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
@@ -37,6 +37,7 @@
 
     private final @NonNull Rect mBounds = new Rect();
     private float mAspectRatio;
+    private boolean mIsStashed;
     private PipReentryState mPipReentryState;
     private ComponentName mLastPipComponentName;
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -54,6 +55,20 @@
         return new Rect(mBounds);
     }
 
+    /**
+     * Dictate where PiP currently should be stashed or not.
+     */
+    public void setStashed(boolean isStashed) {
+        mIsStashed = isStashed;
+    }
+
+    /**
+     * Whether PiP is stashed or not.
+     */
+    public boolean isStashed() {
+        return mIsStashed;
+    }
+
     public void setAspectRatio(float aspectRatio) {
         mAspectRatio = aspectRatio;
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
index 9240b3f..9247c68 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
@@ -33,6 +33,7 @@
 import androidx.dynamicanimation.animation.AnimationHandler.FrameCallbackScheduler;
 import androidx.dynamicanimation.animation.SpringForce;
 
+import com.android.wm.shell.R;
 import com.android.wm.shell.animation.FloatProperties;
 import com.android.wm.shell.animation.PhysicsAnimator;
 import com.android.wm.shell.common.FloatingContentCoordinator;
@@ -60,7 +61,6 @@
     private static final int EXPAND_STACK_TO_MENU_DURATION = 250;
     private static final int LEAVE_PIP_DURATION = 300;
     private static final int SHIFT_DURATION = 300;
-    private static final float STASH_RATIO = 0.25f;
 
     /** Friction to use for PIP when it moves via physics fling animations. */
     private static final float DEFAULT_FRICTION = 2f;
@@ -94,6 +94,8 @@
     /** The destination bounds to which PIP is animating. */
     private final Rect mAnimatingToBounds = new Rect();
 
+    private int mStashOffset = 0;
+
     /** Coordinator instance for resolving conflicts with other floating content. */
     private FloatingContentCoordinator mFloatingContentCoordinator;
 
@@ -189,6 +191,7 @@
         mPipTaskOrganizer.registerPipTransitionCallback(mPipTransitionCallback);
         mTemporaryBoundsPhysicsAnimator.setCustomAnimationHandler(
                 mSfAnimationHandlerThreadLocal.get());
+        reloadResources();
 
         mResizePipUpdateListener = (target, values) -> {
             if (!mTemporaryBounds.isEmpty()) {
@@ -198,6 +201,11 @@
         };
     }
 
+    void reloadResources() {
+        mStashOffset = mContext.getResources()
+                .getDimensionPixelSize(R.dimen.pip_stash_offset);
+    }
+
     @NonNull
     @Override
     public Rect getFloatingBoundsOnScreen() {
@@ -414,9 +422,10 @@
                         FloatProperties.RECT_Y, velocityY, mFlingConfigY, mSpringConfig)
                 .withEndActions(endAction);
 
-        final float offset = ((float) getBounds().width()) * (1.0f - STASH_RATIO);
-        final float leftEdge = isStash ? mMovementBounds.left - offset : mMovementBounds.left;
-        final float rightEdge = isStash ?  mMovementBounds.right + offset : mMovementBounds.right;
+        final float leftEdge = isStash ? mStashOffset - mPipBoundsState.getBounds().width()
+                : mMovementBounds.left;
+        final float rightEdge = isStash ?  mPipBoundsState.getDisplayBounds().right - mStashOffset
+                : mMovementBounds.right;
 
         final float xEndValue = velocityX < 0 ? leftEdge : rightEdge;
         final float estimatedFlingYEndValue =
@@ -524,9 +533,9 @@
                 DEFAULT_FRICTION, mMovementBounds.left, mMovementBounds.right);
         mFlingConfigY = new PhysicsAnimator.FlingConfig(
                 DEFAULT_FRICTION, mMovementBounds.top, mMovementBounds.bottom);
-        final float offset = ((float) getBounds().width()) * (1.0f - STASH_RATIO);
         mStashConfigX = new PhysicsAnimator.FlingConfig(
-                DEFAULT_FRICTION, mMovementBounds.left - offset, mMovementBounds.right + offset);
+                DEFAULT_FRICTION, mStashOffset - mPipBoundsState.getBounds().width(),
+                mPipBoundsState.getDisplayBounds().right - mStashOffset);
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index ef38755..f3d8c7b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -47,6 +47,7 @@
 import com.android.internal.policy.TaskResizingAlgorithm;
 import com.android.wm.shell.R;
 import com.android.wm.shell.pip.PipBoundsHandler;
+import com.android.wm.shell.pip.PipBoundsState;
 import com.android.wm.shell.pip.PipTaskOrganizer;
 import com.android.wm.shell.pip.PipUiEventLogger;
 
@@ -67,6 +68,7 @@
     private final Context mContext;
     private final PipBoundsHandler mPipBoundsHandler;
     private final PipMotionHelper mMotionHelper;
+    private final PipBoundsState mPipBoundsState;
     private final int mDisplayId;
     private final Executor mMainExecutor;
     private final ScaleGestureDetector mScaleGestureDetector;
@@ -107,13 +109,15 @@
     private int mCtrlType;
 
     public PipResizeGestureHandler(Context context, PipBoundsHandler pipBoundsHandler,
-            PipMotionHelper motionHelper, PipTaskOrganizer pipTaskOrganizer,
-            Function<Rect, Rect> movementBoundsSupplier, Runnable updateMovementBoundsRunnable,
-            PipUiEventLogger pipUiEventLogger, PipMenuActivityController menuActivityController) {
+            PipBoundsState pipBoundsState, PipMotionHelper motionHelper,
+            PipTaskOrganizer pipTaskOrganizer, Function<Rect, Rect> movementBoundsSupplier,
+            Runnable updateMovementBoundsRunnable, PipUiEventLogger pipUiEventLogger,
+            PipMenuActivityController menuActivityController) {
         mContext = context;
         mDisplayId = context.getDisplayId();
         mMainExecutor = context.getMainExecutor();
         mPipBoundsHandler = pipBoundsHandler;
+        mPipBoundsState = pipBoundsState;
         mMotionHelper = motionHelper;
         mPipTaskOrganizer = pipTaskOrganizer;
         mMovementBoundsSupplier = movementBoundsSupplier;
@@ -263,6 +267,11 @@
     }
 
     private void onInputEvent(InputEvent ev) {
+        // Don't allow resize when PiP is stashed.
+        if (mPipBoundsState.isStashed()) {
+            return;
+        }
+
         if (ev instanceof MotionEvent) {
             if (mUsingPinchToZoom) {
                 mScaleGestureDetector.onTouchEvent((MotionEvent) ev);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index e95e4a0..d820e77 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -179,8 +179,8 @@
         mMotionHelper = new PipMotionHelper(mContext, pipBoundsState, pipTaskOrganizer,
                 mMenuController, mPipBoundsHandler.getSnapAlgorithm(), floatingContentCoordinator);
         mPipResizeGestureHandler =
-                new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
-                        pipTaskOrganizer, this::getMovementBounds,
+                new PipResizeGestureHandler(context, pipBoundsHandler, pipBoundsState,
+                        mMotionHelper, pipTaskOrganizer, this::getMovementBounds,
                         this::updateMovementBounds, pipUiEventLogger, menuController);
         mPipDismissTargetHandler = new PipDismissTargetHandler(context, pipUiEventLogger,
                 mMotionHelper, mHandler);
@@ -221,6 +221,7 @@
                 R.dimen.pip_expanded_shortest_edge_size);
         mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
         mPipDismissTargetHandler.updateMagneticTargetSize();
+        mMotionHelper.reloadResources();
     }
 
     private boolean shouldShowResizeHandle() {
@@ -463,7 +464,7 @@
         }
 
         MotionEvent ev = (MotionEvent) inputEvent;
-        if (mPipResizeGestureHandler.willStartResizeGesture(ev)) {
+        if (!mPipBoundsState.isStashed() && mPipResizeGestureHandler.willStartResizeGesture(ev)) {
             // Initialize the touch state for the gesture, but immediately reset to invalidate the
             // gesture
             mTouchState.onTouchEvent(ev);
@@ -553,6 +554,8 @@
             }
         }
 
+        shouldDeliverToMenu |= !mPipBoundsState.isStashed();
+
         // Deliver the event to PipMenuActivity to handle button click if the menu has shown.
         if (shouldDeliverToMenu) {
             final MotionEvent cloneEvent = MotionEvent.obtain(ev);
@@ -715,7 +718,7 @@
 
             // If the menu is still visible then just poke the menu
             // so that it will timeout after the user stops touching it
-            if (mMenuState != MENU_STATE_NONE) {
+            if (mMenuState != MENU_STATE_NONE && !mPipBoundsState.isStashed()) {
                 mMenuController.pokeMenu();
             }
         }
@@ -727,6 +730,7 @@
             }
 
             if (touchState.startedDragging()) {
+                mPipBoundsState.setStashed(false);
                 mSavedSnapFraction = -1f;
                 mPipDismissTargetHandler.showDismissTargetMaybe();
             }
@@ -785,12 +789,13 @@
                 if (mEnableStash
                         && (animatingBounds.right > mPipBoundsState.getDisplayBounds().right
                         || animatingBounds.left < mPipBoundsState.getDisplayBounds().left)) {
+                    mPipBoundsState.setStashed(true);
                     mMotionHelper.stashToEdge(vel.x, vel.y, this::flingEndAction /* endAction */);
                 } else {
                     mMotionHelper.flingToSnapTarget(vel.x, vel.y,
                             this::flingEndAction /* endAction */);
                 }
-            } else if (mTouchState.isDoubleTap()) {
+            } else if (mTouchState.isDoubleTap() && !mPipBoundsState.isStashed()) {
                 // If using pinch to zoom, double-tap functions as resizing between max/min size
                 if (mPipResizeGestureHandler.isUsingPinchToZoom()) {
                     final boolean toExpand =
@@ -809,7 +814,7 @@
                     setTouchEnabled(false);
                     mMotionHelper.expandLeavePip();
                 }
-            } else if (mMenuState != MENU_STATE_FULL) {
+            } else if (mMenuState != MENU_STATE_FULL && !mPipBoundsState.isStashed()) {
                 if (!mTouchState.isWaitingForDoubleTap()) {
                     // User has stalled long enough for this not to be a drag or a double tap, just
                     // expand the menu
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 69d428a..8b616e8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -117,7 +117,7 @@
         mTransactionPool = transactionPool;
         mWindowManagerProxy = new WindowManagerProxy(syncQueue, shellTaskOrganizer);
         mTaskOrganizer = shellTaskOrganizer;
-        mSplits = new SplitScreenTaskListener(this, shellTaskOrganizer);
+        mSplits = new SplitScreenTaskListener(this, shellTaskOrganizer, syncQueue);
         mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler,
                 shellTaskOrganizer);
         mRotationController =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
index 191a317..f709fed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
@@ -27,8 +27,10 @@
 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
 
 import android.app.ActivityManager.RunningTaskInfo;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.Log;
+import android.util.SparseArray;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
@@ -36,6 +38,8 @@
 
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.Transitions;
+import com.android.wm.shell.common.SyncTransactionQueue;
 
 import java.io.PrintWriter;
 
@@ -44,6 +48,8 @@
     private static final boolean DEBUG = SplitScreenController.DEBUG;
 
     private final ShellTaskOrganizer mTaskOrganizer;
+    private final SyncTransactionQueue mSyncQueue;
+    private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>();
 
     RunningTaskInfo mPrimary;
     RunningTaskInfo mSecondary;
@@ -58,9 +64,11 @@
     final SurfaceSession mSurfaceSession = new SurfaceSession();
 
     SplitScreenTaskListener(SplitScreenController splitScreenController,
-                    ShellTaskOrganizer shellTaskOrganizer) {
+                    ShellTaskOrganizer shellTaskOrganizer,
+                    SyncTransactionQueue syncQueue) {
         mSplitScreenController = splitScreenController;
         mTaskOrganizer = shellTaskOrganizer;
+        mSyncQueue = syncQueue;
     }
 
     void init() {
@@ -93,6 +101,11 @@
     @Override
     public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
         synchronized (this) {
+            if (taskInfo.hasParentTask()) {
+                handleChildTaskAppeared(taskInfo, leash);
+                return;
+            }
+
             final int winMode = getWindowingMode(taskInfo);
             if (winMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
                 ProtoLog.v(WM_SHELL_TASK_ORG,
@@ -139,6 +152,11 @@
     @Override
     public void onTaskVanished(RunningTaskInfo taskInfo) {
         synchronized (this) {
+            if (taskInfo.hasParentTask()) {
+                mLeashByTaskId.remove(taskInfo.taskId);
+                return;
+            }
+
             final boolean isPrimaryTask = mPrimary != null
                     && taskInfo.token.equals(mPrimary.token);
             final boolean isSecondaryTask = mSecondary != null
@@ -165,7 +183,41 @@
         if (taskInfo.displayId != DEFAULT_DISPLAY) {
             return;
         }
-        mSplitScreenController.post(() -> handleTaskInfoChanged(taskInfo));
+        synchronized (this) {
+            if (taskInfo.hasParentTask()) {
+                handleChildTaskChanged(taskInfo);
+                return;
+            }
+
+            mSplitScreenController.post(() -> handleTaskInfoChanged(taskInfo));
+        }
+    }
+
+    private void handleChildTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
+        mLeashByTaskId.put(taskInfo.taskId, leash);
+        updateChildTaskSurface(taskInfo, leash, true /* firstAppeared */);
+    }
+
+    private void handleChildTaskChanged(RunningTaskInfo taskInfo) {
+        final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
+        updateChildTaskSurface(taskInfo, leash, false /* firstAppeared */);
+    }
+
+    private void updateChildTaskSurface(
+            RunningTaskInfo taskInfo, SurfaceControl leash, boolean firstAppeared) {
+        final Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds();
+        final Point taskPositionInParent = taskInfo.positionInParent;
+        final Rect corp =  new Rect(taskBounds);
+        corp.offset(-taskBounds.left, -taskBounds.top);
+        mSyncQueue.runInSync(t -> {
+            t.setWindowCrop(leash, corp);
+            t.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y);
+            if (firstAppeared && !Transitions.ENABLE_SHELL_TRANSITIONS) {
+                t.setAlpha(leash, 1f);
+                t.setMatrix(leash, 1, 0, 0, 1);
+                t.show(leash);
+            }
+        });
     }
 
     /**
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 35a2293c..e4155a2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -248,6 +248,20 @@
     }
 
     @Test
+    public void testGetParentTaskListener() {
+        RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+        TrackingTaskListener mwListener = new TrackingTaskListener();
+        mOrganizer.onTaskAppeared(task1, null);
+        mOrganizer.addListenerForTaskId(mwListener, task1.taskId);
+        RunningTaskInfo task2 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+        task2.parentTaskId = task1.taskId;
+
+        mOrganizer.onTaskAppeared(task2, null);
+
+        assertTrue(mwListener.appeared.contains(task2));
+    }
+
+    @Test
     public void testTaskInfoToTaskListenerType_whenLetterboxBoundsPassed_returnsLetterboxType() {
         RunningTaskInfo taskInfo = createTaskInfo(
                 /* taskId */ 1,
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 79b8611..610bffe 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
 import android.hardware.HardwareBuffer;
@@ -58,6 +59,7 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @TestApi
     protected Image() {
     }
 
@@ -387,6 +389,7 @@
          * @hide
          */
         @UnsupportedAppUsage
+        @TestApi
         protected Plane() {
         }
 
diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java
index 9fc3a23..dd386b0 100644
--- a/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java
@@ -25,7 +25,7 @@
  * @hide
  */
 @SystemApi
-public class DtmbFrontendCapabilities extends FrontendCapabilities {
+public final class DtmbFrontendCapabilities extends FrontendCapabilities {
     private final int mModulationCap;
     private final int mTransmissionModeCap;
     private final int mGuardIntervalCap;
diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
index 2c3fe6a..d85e60d 100644
--- a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
@@ -34,7 +34,7 @@
  * @hide
  */
 @SystemApi
-public class DtmbFrontendSettings extends FrontendSettings {
+public final class DtmbFrontendSettings extends FrontendSettings {
 
     /** @hide */
     @IntDef(flag = true,
diff --git a/packages/CompanionDeviceManager/res/layout/buttons.xml b/packages/CompanionDeviceManager/res/layout/buttons.xml
index 7de0035..b190a7f 100644
--- a/packages/CompanionDeviceManager/res/layout/buttons.xml
+++ b/packages/CompanionDeviceManager/res/layout/buttons.xml
@@ -30,13 +30,13 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="@android:string/cancel"
-        style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
+        style="@android:style/Widget.Material.Button.Borderless.Colored"
     />
     <Button
         android:id="@+id/button_pair"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="@android:string/ok"
-        style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
+        style="@android:style/Widget.Material.Button.Borderless.Colored"
     />
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/device_chooser.xml b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
index 88de33f..db014ae 100644
--- a/packages/CompanionDeviceManager/res/layout/device_chooser.xml
+++ b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
@@ -29,7 +29,7 @@
         android:layout_height="match_parent"
         android:layout_below="@+id/title"
         android:layout_above="@+id/buttons"
-        style="@android:style/Widget.Material.Light.ListView"
+        style="@android:style/Widget.Material.ListView"
     />
 
     <include layout="@layout/buttons" />
diff --git a/packages/CompanionDeviceManager/res/layout/title.xml b/packages/CompanionDeviceManager/res/layout/title.xml
index dfa71e2..0a44fbb 100644
--- a/packages/CompanionDeviceManager/res/layout/title.xml
+++ b/packages/CompanionDeviceManager/res/layout/title.xml
@@ -20,6 +20,5 @@
     android:id="@+id/title"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:textColor="@android:color/black"
     style="@*android:style/TextAppearance.Widget.Toolbar.Title"
 />
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values/themes.xml b/packages/CompanionDeviceManager/res/values/themes.xml
index e3fc67c..66729347 100644
--- a/packages/CompanionDeviceManager/res/values/themes.xml
+++ b/packages/CompanionDeviceManager/res/values/themes.xml
@@ -21,6 +21,7 @@
         <item name="*android:windowFixedHeightMajor">100%</item>
         <item name="*android:windowFixedHeightMinor">100%</item>
         <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:forceDarkAllowed">true</item>
     </style>
 
 </resources>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index f108e06..c5876af 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -49,6 +49,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.net.wifi.WifiManager;
@@ -58,6 +59,8 @@
 import android.os.RemoteException;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.SparseArray;
+import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
@@ -317,6 +320,8 @@
         private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
         private Drawable WIFI_ICON = icon(com.android.internal.R.drawable.ic_wifi_signal_3);
 
+        private SparseArray<Integer> mColors = new SparseArray();
+
         private Drawable icon(int drawableRes) {
             Drawable icon = getResources().getDrawable(drawableRes, null);
             icon.setTint(Color.DKGRAY);
@@ -343,24 +348,36 @@
             textView.setText(device.getDisplayName());
             textView.setBackgroundColor(
                     device.equals(mSelectedDevice)
-                            ? Color.GRAY
+                            ? getColor(android.R.attr.colorControlHighlight)
                             : Color.TRANSPARENT);
             textView.setCompoundDrawablesWithIntrinsicBounds(
                     device.device instanceof android.net.wifi.ScanResult
                         ? WIFI_ICON
                         : BLUETOOTH_ICON,
                     null, null, null);
+            textView.getCompoundDrawables()[0].setTint(getColor(android.R.attr.colorForeground));
         }
 
-        //TODO move to a layout file
         private TextView newView() {
             final TextView textView = new TextView(DeviceDiscoveryService.this);
-            textView.setTextColor(Color.BLACK);
+            textView.setTextColor(getColor(android.R.attr.colorForeground));
             final int padding = DeviceChooserActivity.getPadding(getResources());
             textView.setPadding(padding, padding, padding, padding);
             textView.setCompoundDrawablePadding(padding);
             return textView;
         }
+
+        private int getColor(int colorAttr) {
+            if (mColors.contains(colorAttr)) {
+                return mColors.get(colorAttr);
+            }
+            TypedValue typedValue = new TypedValue();
+            TypedArray a = obtainStyledAttributes(typedValue.data, new int[] { colorAttr });
+            int result = a.getColor(0, 0);
+            a.recycle();
+            mColors.put(colorAttr, result);
+            return result;
+        }
     }
 
     /**
diff --git a/packages/DynamicSystemInstallationService/res/values-af/strings.xml b/packages/DynamicSystemInstallationService/res/values-af/strings.xml
index 1829d34..1b300358 100644
--- a/packages/DynamicSystemInstallationService/res/values-af/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-af/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Herbegin"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Het dinamiese stelsel weggegooi"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Kan nie dinamiese stelsel herbegin of laai nie"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-am/strings.xml b/packages/DynamicSystemInstallationService/res/values-am/strings.xml
index 7fcc40d..a8a7b00 100644
--- a/packages/DynamicSystemInstallationService/res/values-am/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-am/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ዳግም ጀምር"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"የተጣለ ተለዋዋጭ ሥርዓት"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ዳግም ማስጀመር አይቻልም ወይም ተለዋዋጭ ሥርዓትን ይስቀሉ"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ar/strings.xml b/packages/DynamicSystemInstallationService/res/values-ar/strings.xml
index be705c3..44a6503 100644
--- a/packages/DynamicSystemInstallationService/res/values-ar/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ar/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"إعادة التشغيل"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"تم تجاهل النظام الديناميكي."</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"لا يمكن إعادة التشغيل أو تحميل النظام الديناميكي."</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-as/strings.xml b/packages/DynamicSystemInstallationService/res/values-as/strings.xml
index 14eead9..e93ad9b 100644
--- a/packages/DynamicSystemInstallationService/res/values-as/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-as/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ৰিষ্টাৰ্ট কৰক"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"বাতিল কৰা ডায়নামিক ছিষ্টেম"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ডায়নামিক ছিষ্টেম ৰিষ্টার্ট অথবা ল\'ড কৰিব নোৱাৰি"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-az/strings.xml b/packages/DynamicSystemInstallationService/res/values-az/strings.xml
index d1f0a4b..ad3d3e7 100644
--- a/packages/DynamicSystemInstallationService/res/values-az/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-az/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Yenidən başladın"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamik sistemdən imtina edildi"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dinamik sistemi yenidən başlatmaq və ya yükləmək mümkün deyil"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-b+sr+Latn/strings.xml b/packages/DynamicSystemInstallationService/res/values-b+sr+Latn/strings.xml
index ea23a28..0107047 100644
--- a/packages/DynamicSystemInstallationService/res/values-b+sr+Latn/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-b+sr+Latn/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restartuj"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamični sistem je odbačen"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Restartovanje ili učitavanje dinamičnog sistema nije uspelo"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-be/strings.xml b/packages/DynamicSystemInstallationService/res/values-be/strings.xml
index 7eef297..5a52f73 100644
--- a/packages/DynamicSystemInstallationService/res/values-be/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-be/strings.xml
@@ -5,7 +5,7 @@
     <string name="notification_install_completed" msgid="6252047868415172643">"Дынамічная сістэма гатовая. Каб пачаць выкарыстоўваць яе, перазапусціце прыладу."</string>
     <string name="notification_install_inprogress" msgid="7383334330065065017">"Ідзе ўсталёўка"</string>
     <string name="notification_install_failed" msgid="4066039210317521404">"Збой усталёўкі"</string>
-    <string name="notification_image_validation_failed" msgid="2720357826403917016">"Збой пры праверцы відарыса. Усталёўка спынена."</string>
+    <string name="notification_image_validation_failed" msgid="2720357826403917016">"Збой пры праверцы вобраза дыска. Усталёўка спынена."</string>
     <string name="notification_dynsystem_in_use" msgid="1053194595682188396">"Цяпер запушчана дынамічная сістэма. Перазапусціце, каб скарыстаць арыгінальную версію Android."</string>
     <string name="notification_action_cancel" msgid="5929299408545961077">"Скасаваць"</string>
     <string name="notification_action_discard" msgid="1817481003134947493">"Адхіліць"</string>
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Перазапусціць"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Дынамічная сістэма адхілена"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Не ўдалося перазапусціць або загрузіць дынамічную сістэму"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-bg/strings.xml b/packages/DynamicSystemInstallationService/res/values-bg/strings.xml
index 9176676..194bf2d 100644
--- a/packages/DynamicSystemInstallationService/res/values-bg/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-bg/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Рестартиране"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамичната система е отхвърлена"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Динамичната система не може да се рестартира или зареди"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-bn/strings.xml b/packages/DynamicSystemInstallationService/res/values-bn/strings.xml
index 38ef649..43886b3 100644
--- a/packages/DynamicSystemInstallationService/res/values-bn/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-bn/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"রিস্টার্ট করুন"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ডায়নামিক সিস্টেম বাতিল করা হয়েছে"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ডায়নামিক সিস্টেম রিস্টার্ট বা লোড করা যাচ্ছে না"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-bs/strings.xml b/packages/DynamicSystemInstallationService/res/values-bs/strings.xml
index 84ba540..342230b2 100644
--- a/packages/DynamicSystemInstallationService/res/values-bs/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-bs/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Ponovo pokreni"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamični sistem je odbačen"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nije moguće ponovo pokrenuti ili učitati dinamični sistem"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ca/strings.xml b/packages/DynamicSystemInstallationService/res/values-ca/strings.xml
index 787e496..e9e4d35 100644
--- a/packages/DynamicSystemInstallationService/res/values-ca/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ca/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reinicia"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"S\'ha descartat el sistema dinàmic"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"No es pot reiniciar ni carregar el sistema dinàmic"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-cs/strings.xml b/packages/DynamicSystemInstallationService/res/values-cs/strings.xml
index 3dfb23f..6ae71c6 100644
--- a/packages/DynamicSystemInstallationService/res/values-cs/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-cs/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restartovat"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Zahodit dynamický systém"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dynamický systém nelze znovu spustit nebo načíst"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-da/strings.xml b/packages/DynamicSystemInstallationService/res/values-da/strings.xml
index 20005e7..10b798c 100644
--- a/packages/DynamicSystemInstallationService/res/values-da/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-da/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Genstart"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Det dynamiske system blev slettet"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Det dynamiske system kan ikke genstartes eller indlæses"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-de/strings.xml b/packages/DynamicSystemInstallationService/res/values-de/strings.xml
index 3f000ea..82459b2 100644
--- a/packages/DynamicSystemInstallationService/res/values-de/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-de/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Neu starten"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynamisches System verworfen"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Neustart und Laden des dynamischen Systems nicht möglich"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-el/strings.xml b/packages/DynamicSystemInstallationService/res/values-el/strings.xml
index 4d830dd..ef02906 100644
--- a/packages/DynamicSystemInstallationService/res/values-el/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-el/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Επανεκκίνηση"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Οι δυναμικές συστήματος απορρίφθηκαν."</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Δεν είναι δυνατή η επανεκκίνηση ή η φόρτωση δυναμικών συστήματος"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-en-rAU/strings.xml b/packages/DynamicSystemInstallationService/res/values-en-rAU/strings.xml
index d728631..6f3f887 100644
--- a/packages/DynamicSystemInstallationService/res/values-en-rAU/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-en-rAU/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restart"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Discarded dynamic system"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Can’t restart or load dynamic system"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-en-rCA/strings.xml b/packages/DynamicSystemInstallationService/res/values-en-rCA/strings.xml
index d728631..6f3f887 100644
--- a/packages/DynamicSystemInstallationService/res/values-en-rCA/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-en-rCA/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restart"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Discarded dynamic system"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Can’t restart or load dynamic system"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-en-rGB/strings.xml b/packages/DynamicSystemInstallationService/res/values-en-rGB/strings.xml
index d728631..6f3f887 100644
--- a/packages/DynamicSystemInstallationService/res/values-en-rGB/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-en-rGB/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restart"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Discarded dynamic system"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Can’t restart or load dynamic system"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-en-rIN/strings.xml b/packages/DynamicSystemInstallationService/res/values-en-rIN/strings.xml
index d728631..6f3f887 100644
--- a/packages/DynamicSystemInstallationService/res/values-en-rIN/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-en-rIN/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restart"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Discarded dynamic system"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Can’t restart or load dynamic system"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-en-rXC/strings.xml b/packages/DynamicSystemInstallationService/res/values-en-rXC/strings.xml
index 6ac3763..2e83672 100644
--- a/packages/DynamicSystemInstallationService/res/values-en-rXC/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-en-rXC/strings.xml
@@ -13,4 +13,5 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎Restart‎‏‎‎‏‎"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎Discarded dynamic system‎‏‎‎‏‎"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‏‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‎Can’t restart or load dynamic system‎‏‎‎‏‎"</string>
+    <string name="toast_failed_to_disable_dynsystem" msgid="3285742944977744413">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‏‎Failed to disable dynamic system‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-es-rUS/strings.xml b/packages/DynamicSystemInstallationService/res/values-es-rUS/strings.xml
index 9ec8196..aeb65be 100644
--- a/packages/DynamicSystemInstallationService/res/values-es-rUS/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-es-rUS/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Se descartó el sistema dinámico"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"No se puede reiniciar o cargar el sistema dinámico"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-es/strings.xml b/packages/DynamicSystemInstallationService/res/values-es/strings.xml
index cd9db07..0c3ae53 100644
--- a/packages/DynamicSystemInstallationService/res/values-es/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-es/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Se ha descartado el sistema dinámico"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"No se ha podido reiniciar o cargar el sistema dinámico"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-et/strings.xml b/packages/DynamicSystemInstallationService/res/values-et/strings.xml
index 64968b60..ab20a04 100644
--- a/packages/DynamicSystemInstallationService/res/values-et/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-et/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Taaskäivita"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dünaamilisest süsteemist loobuti"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dünaamilist süsteemi ei saa taaskäivitada ega laadida"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-eu/strings.xml b/packages/DynamicSystemInstallationService/res/values-eu/strings.xml
index 7c4a67d..1863778 100644
--- a/packages/DynamicSystemInstallationService/res/values-eu/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-eu/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Berrabiarazi"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Baztertu da sistema dinamikoa"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Ezin da berrabiarazi edo kargatu sistema dinamikoa"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-fa/strings.xml b/packages/DynamicSystemInstallationService/res/values-fa/strings.xml
index 7533e71..5b0b218 100644
--- a/packages/DynamicSystemInstallationService/res/values-fa/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-fa/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"بازراه‌اندازی"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"از سیستم پویا صرف‌نظر شد"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"نمی‌توان سیستم پویا را بازراه‌اندازی یا بار کرد"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-fi/strings.xml b/packages/DynamicSystemInstallationService/res/values-fi/strings.xml
index 948c333..b4315e7 100644
--- a/packages/DynamicSystemInstallationService/res/values-fi/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-fi/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Käynn. uudelleen"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynaaminen järjestelmä hylätty"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dynaamista järjestelmää ei voi käynnistää uudelleen tai ladata"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-fr-rCA/strings.xml b/packages/DynamicSystemInstallationService/res/values-fr-rCA/strings.xml
index 6e2f235..973efef 100644
--- a/packages/DynamicSystemInstallationService/res/values-fr-rCA/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-fr-rCA/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Redémarrer"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Système dynamique supprimé"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Impossible de redémarrer ou de charger le système dynamique"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-fr/strings.xml b/packages/DynamicSystemInstallationService/res/values-fr/strings.xml
index 67f7997..5422e8e 100644
--- a/packages/DynamicSystemInstallationService/res/values-fr/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-fr/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Redémarrer"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Système dynamique supprimé"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Impossible de redémarrer ou de charger le système dynamique"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-gl/strings.xml b/packages/DynamicSystemInstallationService/res/values-gl/strings.xml
index 8ea6d1c..e24f495a 100644
--- a/packages/DynamicSystemInstallationService/res/values-gl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-gl/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Descartouse o sistema dinámico"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Non se puido reiniciar nin cargar o sistema dinámico"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-gu/strings.xml b/packages/DynamicSystemInstallationService/res/values-gu/strings.xml
index aec1804..6c2e673 100644
--- a/packages/DynamicSystemInstallationService/res/values-gu/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-gu/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ફરી શરૂ કરો"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ડાઇનૅમિક સિસ્ટમ કાઢી નાખવામાં આવી"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ડાઇનૅમિક સિસ્ટમને ફરી શરૂ અથવા લોડ કરી શકાતી નથી"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-hi/strings.xml b/packages/DynamicSystemInstallationService/res/values-hi/strings.xml
index efedbe8..13dc9e8 100644
--- a/packages/DynamicSystemInstallationService/res/values-hi/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-hi/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"रीस्टार्ट करें"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"डाइनैमिक सिस्टम खारिज किया गया"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"डाइनैमिक सिस्टम रीस्टार्ट या लोड नहीं हो सका"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-hr/strings.xml b/packages/DynamicSystemInstallationService/res/values-hr/strings.xml
index 50ceaa1..3318d20 100644
--- a/packages/DynamicSystemInstallationService/res/values-hr/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-hr/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Pokreni"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Odbačeni dinamični sustav"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nije moguće ponovno pokretanje ili učitavanje dinamičnog sustava"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-hu/strings.xml b/packages/DynamicSystemInstallationService/res/values-hu/strings.xml
index 94afa3b..208ab3b 100644
--- a/packages/DynamicSystemInstallationService/res/values-hu/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-hu/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Újraindítás"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Elvetett dinamikus rendszer"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nem lehet újraindítani vagy betölteni a dinamikus rendszert"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-hy/strings.xml b/packages/DynamicSystemInstallationService/res/values-hy/strings.xml
index b0cd740..4dcc72e 100644
--- a/packages/DynamicSystemInstallationService/res/values-hy/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-hy/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Վերագործարկել"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Դինամիկ համակարգի գործարկումը չեղարկվեց"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Չհաջողվեց վերագործարկել կամ բեռնել դինամիկ համակարգը"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-in/strings.xml b/packages/DynamicSystemInstallationService/res/values-in/strings.xml
index 44b4aee..2fa4f11 100644
--- a/packages/DynamicSystemInstallationService/res/values-in/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-in/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Mulai ulang"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynamic System dihapus"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Tidak dapat memulai ulang atau memuat Dynamic System"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-is/strings.xml b/packages/DynamicSystemInstallationService/res/values-is/strings.xml
index 048d1bc..ef7484c 100644
--- a/packages/DynamicSystemInstallationService/res/values-is/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-is/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Endurræsa"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Breytilegu kerfi fleygt"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Ekki tókst að endurræsa eða hlaða breytilegu kerfi"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-it/strings.xml b/packages/DynamicSystemInstallationService/res/values-it/strings.xml
index f70b381..c8fa41b 100644
--- a/packages/DynamicSystemInstallationService/res/values-it/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-it/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Riavvia"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistema dinamico annullato"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Impossibile riavviare o caricare il sistema dinamico"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-iw/strings.xml b/packages/DynamicSystemInstallationService/res/values-iw/strings.xml
index aff7c82..d9bf983 100644
--- a/packages/DynamicSystemInstallationService/res/values-iw/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-iw/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"הפעלה מחדש"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"המערכת הדינמית נסגרה"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"לא ניתן להפעיל מחדש או לטעון את המערכת הדינמית"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ja/strings.xml b/packages/DynamicSystemInstallationService/res/values-ja/strings.xml
index 46c0930..2082d91 100644
--- a/packages/DynamicSystemInstallationService/res/values-ja/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ja/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"再起動"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"動的システムを破棄しました"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"動的システムの再起動や読み込みを行えません"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ka/strings.xml b/packages/DynamicSystemInstallationService/res/values-ka/strings.xml
index f841a59..e57de2c 100644
--- a/packages/DynamicSystemInstallationService/res/values-ka/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ka/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"გადატვირთვა"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"გაუქმებული დინამიური სისტემა"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"დინამიური სისტემის გადატვირთვა ან ჩატვირთვა ვერ ხერხდება"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-kk/strings.xml b/packages/DynamicSystemInstallationService/res/values-kk/strings.xml
index d367b61..da10e9c 100644
--- a/packages/DynamicSystemInstallationService/res/values-kk/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-kk/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Қайта қосу"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамикалық жүйе өшірілді."</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Динамикалық жүйені қайта қосу не жүктеу мүмкін емес."</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-km/strings.xml b/packages/DynamicSystemInstallationService/res/values-km/strings.xml
index 56a3716..7bb5980 100644
--- a/packages/DynamicSystemInstallationService/res/values-km/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-km/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ចាប់ផ្ដើមឡើងវិញ"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"បានលុបចោល​ប្រព័ន្ធឌីណាមិច"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"មិនអាច​ចាប់ផ្ដើមឡើងវិញ ឬផ្ទុក​ប្រព័ន្ធឌីណាមិច​បានទេ"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-kn/strings.xml b/packages/DynamicSystemInstallationService/res/values-kn/strings.xml
index b4063df..f41f2ef 100644
--- a/packages/DynamicSystemInstallationService/res/values-kn/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-kn/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ಮರುಪ್ರಾರಂಭಿಸಿ"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ಡೈನಮಿಕ್ ಸಿಸ್ಟಂ ಅನ್ನು ತ್ಯಜಿಸಲಾಗಿದೆ"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ಡೈನಾಮಿಕ್ ಸಿಸ್ಟಂ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಲು ಅಥವಾ ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ko/strings.xml b/packages/DynamicSystemInstallationService/res/values-ko/strings.xml
index 24ac924..bca9e07 100644
--- a/packages/DynamicSystemInstallationService/res/values-ko/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ko/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"다시 시작"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"동적 시스템 삭제됨"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"동적 시스템을 다시 시작하거나 로드할 수 없음"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ky/strings.xml b/packages/DynamicSystemInstallationService/res/values-ky/strings.xml
index a4387e7..d2ad56a 100644
--- a/packages/DynamicSystemInstallationService/res/values-ky/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ky/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Өчүрүп күйгүзүү"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамикалык система жоюлду"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Динамикалык система өчүрүлүп күйгүзүлбөй же жүктөлбөй жатат"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-lo/strings.xml b/packages/DynamicSystemInstallationService/res/values-lo/strings.xml
index f17ca16..a732aa4 100644
--- a/packages/DynamicSystemInstallationService/res/values-lo/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-lo/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ຣີສະຕາດ"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ລະບົບໄດນາມິກທີ່ຍົກເລີກແລ້ວ"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ບໍ່ສາມາດຣີສະຕາດ ຫຼື ໂຫຼດລະບົບໄດນາມິກໄດ້"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-lt/strings.xml b/packages/DynamicSystemInstallationService/res/values-lt/strings.xml
index 8128eb7..b25c62a 100644
--- a/packages/DynamicSystemInstallationService/res/values-lt/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-lt/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Pal. iš naujo"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinaminė sistema atmesta"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nepavyko paleisti iš naujo ar įkelti dinaminės sistemos"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-lv/strings.xml b/packages/DynamicSystemInstallationService/res/values-lv/strings.xml
index cfe7a08..4ca6ace 100644
--- a/packages/DynamicSystemInstallationService/res/values-lv/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-lv/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restartēt"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamiskā sistēma tika atmesta"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nevar restartēt vai ielādēt dinamisko sistēmu"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-mk/strings.xml b/packages/DynamicSystemInstallationService/res/values-mk/strings.xml
index 21215aa..52a52a5 100644
--- a/packages/DynamicSystemInstallationService/res/values-mk/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-mk/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Рестартирај"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Отфрлен динамичен систем"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Не може да го рестартира или вчита динамичниот систем"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ml/strings.xml b/packages/DynamicSystemInstallationService/res/values-ml/strings.xml
index 951a0b9..2504069 100644
--- a/packages/DynamicSystemInstallationService/res/values-ml/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ml/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"റീസ്റ്റാർട്ട് ചെയ്യൂ"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ഡെെനാമിക് സിസ്റ്റം നിരസിച്ചു"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"റീസ്റ്റാർട്ട് ചെയ്യാനോ ഡെെനാമിക് സിസ്റ്റം ലോഡ് ചെയ്യാനോ ആവില്ല"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-mn/strings.xml b/packages/DynamicSystemInstallationService/res/values-mn/strings.xml
index d0965d0..fe93f65 100644
--- a/packages/DynamicSystemInstallationService/res/values-mn/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-mn/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Дахин эхлүүлэх"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамик системийг устгасан"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Динамик системийг дахин эхлүүлэх эсвэл ачаалах боломжгүй байна"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-mr/strings.xml b/packages/DynamicSystemInstallationService/res/values-mr/strings.xml
index 268e1d3..5f27af0 100644
--- a/packages/DynamicSystemInstallationService/res/values-mr/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-mr/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"रीस्टार्ट करा"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"डायनॅमिक सिस्टम काढून टाकली"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"डायनॅमिक सिस्टम रीस्टार्ट किंवा लोड करू शकत नाही"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ms/strings.xml b/packages/DynamicSystemInstallationService/res/values-ms/strings.xml
index bba8b97..797152c 100644
--- a/packages/DynamicSystemInstallationService/res/values-ms/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ms/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Mulakan semula"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistem dinamik dibuang"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Tidak dapat memulakan semula atau memuatkan sistem dinamik"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-my/strings.xml b/packages/DynamicSystemInstallationService/res/values-my/strings.xml
index b2488ec..3ee85b2 100644
--- a/packages/DynamicSystemInstallationService/res/values-my/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-my/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ပြန်စရန်"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ပြောင်းလဲနိုင်သောစနစ်ကို ဖယ်လိုက်သည်"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ပြန်စ၍ မရပါ (သို့) ပြောင်းလဲနိုင်သောစနစ် ဖွင့်၍မရပါ"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-nb/strings.xml b/packages/DynamicSystemInstallationService/res/values-nb/strings.xml
index 36e3d69..88087e5 100644
--- a/packages/DynamicSystemInstallationService/res/values-nb/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-nb/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Start på nytt"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Det dynamiske systemet er forkastet"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Det dynamiske systemet kan ikke startes på nytt eller lastes inn"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ne/strings.xml b/packages/DynamicSystemInstallationService/res/values-ne/strings.xml
index ee92678..da98fee 100644
--- a/packages/DynamicSystemInstallationService/res/values-ne/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ne/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"रिस्टार्ट गर्नु…"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynamic System खारेज गरियो"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"रिस्टार्ट गर्न वा Dynamic System लोड गर्न सकिएन"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-nl/strings.xml b/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
index 2b9fa41..5120c90 100644
--- a/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Herstarten"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynamisch systeem niet opgeslagen"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Kan dynamisch systeem niet opnieuw opstarten of laden"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-or/strings.xml b/packages/DynamicSystemInstallationService/res/values-or/strings.xml
index e0c8470..878947e 100644
--- a/packages/DynamicSystemInstallationService/res/values-or/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-or/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ରିଷ୍ଟାର୍ଟ କରନ୍ତୁ"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ଡାଇନାମିକ୍ ସିଷ୍ଟମ୍ ଖାରଜ କରାଯାଇଛି"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ଡାଇନାମିକ୍ ସିଷ୍ଟମ୍ ରିଷ୍ଟାର୍ଟ କିମ୍ବା ଲୋଡ୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-pa/strings.xml b/packages/DynamicSystemInstallationService/res/values-pa/strings.xml
index c5f7a3d..2695aaf 100644
--- a/packages/DynamicSystemInstallationService/res/values-pa/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-pa/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ਮੁੜ-ਸ਼ੁਰੂ ਕਰੋ"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ਪਰਿਵਰਤਨਸ਼ੀਲ ਸਿਸਟਮ ਰੱਦ ਕੀਤਾ ਗਿਆ"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ਪਰਿਵਰਤਨਸ਼ੀਲ ਸਿਸਟਮ ਮੁੜ-ਸ਼ੁਰੂ ਜਾਂ ਲੋਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-pl/strings.xml b/packages/DynamicSystemInstallationService/res/values-pl/strings.xml
index bc7d5fe..33592c8 100644
--- a/packages/DynamicSystemInstallationService/res/values-pl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-pl/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Uruchom ponownie"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Usunięto system dynamiczny"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nie można ponownie uruchomić lub wczytać systemu dynamicznego"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-pt-rBR/strings.xml b/packages/DynamicSystemInstallationService/res/values-pt-rBR/strings.xml
index 31a9bb4..43bd021 100644
--- a/packages/DynamicSystemInstallationService/res/values-pt-rBR/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-pt-rBR/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistema dinâmico descartado"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Não é possível reiniciar ou carregar o sistema dinâmico"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-pt-rPT/strings.xml b/packages/DynamicSystemInstallationService/res/values-pt-rPT/strings.xml
index d917c6a..dc29a65 100644
--- a/packages/DynamicSystemInstallationService/res/values-pt-rPT/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-pt-rPT/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistema dinâmico rejeitado"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Não é possível reiniciar ou carregar o sistema dinâmico."</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-pt/strings.xml b/packages/DynamicSystemInstallationService/res/values-pt/strings.xml
index 31a9bb4..43bd021 100644
--- a/packages/DynamicSystemInstallationService/res/values-pt/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-pt/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistema dinâmico descartado"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Não é possível reiniciar ou carregar o sistema dinâmico"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ro/strings.xml b/packages/DynamicSystemInstallationService/res/values-ro/strings.xml
index c211318..c9d391a 100644
--- a/packages/DynamicSystemInstallationService/res/values-ro/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ro/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reporniți"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"S-a renunțat la sistemul dinamic"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nu se poate reporni sau încărca sistemul dinamic"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ru/strings.xml b/packages/DynamicSystemInstallationService/res/values-ru/strings.xml
index bf94c99..cba9a71 100644
--- a/packages/DynamicSystemInstallationService/res/values-ru/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ru/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Перезапустить"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамическая система удалена."</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Не удается запустить или загрузить динамическую систему."</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-si/strings.xml b/packages/DynamicSystemInstallationService/res/values-si/strings.xml
index e6a6ea2..7aab6e9 100644
--- a/packages/DynamicSystemInstallationService/res/values-si/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-si/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"යළි අරඹන්න"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ගතික පද්ධතිය ඉවත දමන ලදි"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ගතික පද්ධතිය නැවත ආරම්භ කිරීමට හෝ පූරණය කිරීමට නොහැක"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sk/strings.xml b/packages/DynamicSystemInstallationService/res/values-sk/strings.xml
index 99390cf..61c176f 100644
--- a/packages/DynamicSystemInstallationService/res/values-sk/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sk/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reštartovať"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Zahodený dynamický systém"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nie je možné reštartovať alebo načítať dynamický systém"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sl/strings.xml b/packages/DynamicSystemInstallationService/res/values-sl/strings.xml
index 3ffd741..0be1248 100644
--- a/packages/DynamicSystemInstallationService/res/values-sl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sl/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Znova zaženi"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamični sistem je bil zavržen"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dinamičnega sistema ni mogoče znova zagnati ali naložiti"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sq/strings.xml b/packages/DynamicSystemInstallationService/res/values-sq/strings.xml
index 704b512..43a5f7b 100644
--- a/packages/DynamicSystemInstallationService/res/values-sq/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sq/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Rinis"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistemi dinamik u hoq"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Sistemi dinamik nuk mund të rinisej ose të ngarkohej"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sr/strings.xml b/packages/DynamicSystemInstallationService/res/values-sr/strings.xml
index 5e4540a..a5ba656 100644
--- a/packages/DynamicSystemInstallationService/res/values-sr/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sr/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Рестартуј"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамични систем је одбачен"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Рестартовање или учитавање динамичног система није успело"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sv/strings.xml b/packages/DynamicSystemInstallationService/res/values-sv/strings.xml
index 546ffdd..99e6752 100644
--- a/packages/DynamicSystemInstallationService/res/values-sv/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sv/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Starta om"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Det dynamiska systemet ignorerades"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Det gick inte att starta om eller läsa in det dynamiska systemet"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sw/strings.xml b/packages/DynamicSystemInstallationService/res/values-sw/strings.xml
index 53414d5..8af9ad3 100644
--- a/packages/DynamicSystemInstallationService/res/values-sw/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sw/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Zima kisha uwashe"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Umeondoa Dynamic System"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Imeshindwa kuzima na kuwasha au kupakia Dynamic System"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ta/strings.xml b/packages/DynamicSystemInstallationService/res/values-ta/strings.xml
index e0aaaf7..bbe8c4e 100644
--- a/packages/DynamicSystemInstallationService/res/values-ta/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ta/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"மீண்டும் தொடங்கு"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynamic system நிராகரிக்கப்பட்டது"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dynamic systemமை மீண்டும் தொடங்கவோ ஏற்றவோ முடியவில்லை"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-te/strings.xml b/packages/DynamicSystemInstallationService/res/values-te/strings.xml
index d497630..4a9433e7 100644
--- a/packages/DynamicSystemInstallationService/res/values-te/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-te/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"రీస్టార్ట్ చేయి"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"డైనమిక్ సిస్టమ్ విస్మరించబడింది"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"డైనమిక్ సిస్టమ్‌ను రీస్టార్ట్ చేయడం లేదా లోడ్ చేయడం సాధ్యపడలేదు"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-th/strings.xml b/packages/DynamicSystemInstallationService/res/values-th/strings.xml
index 786324f..5b81a03 100644
--- a/packages/DynamicSystemInstallationService/res/values-th/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-th/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"รีสตาร์ท"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ยกเลิกระบบแบบไดนามิกแล้ว"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"รีสตาร์ทหรือโหลดระบบแบบไดนามิกไม่ได้"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-tl/strings.xml b/packages/DynamicSystemInstallationService/res/values-tl/strings.xml
index df39f7b..d6c2f15 100644
--- a/packages/DynamicSystemInstallationService/res/values-tl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-tl/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"I-restart"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Na-discard ang dynamic system"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Hindi ma-restart o ma-load ang dynamic system"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-tr/strings.xml b/packages/DynamicSystemInstallationService/res/values-tr/strings.xml
index 1446f96..a98526e 100644
--- a/packages/DynamicSystemInstallationService/res/values-tr/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-tr/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Yeniden başlat"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamik sistem silindi"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dinamik sistem yeniden başlatılamıyor veya yüklenemiyor"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-uk/strings.xml b/packages/DynamicSystemInstallationService/res/values-uk/strings.xml
index 9a44d97..6526787 100644
--- a/packages/DynamicSystemInstallationService/res/values-uk/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-uk/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Перезапустити"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамічну систему видалено"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Не вдається перезапустити пристрій або завантажити динамічну систему"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ur/strings.xml b/packages/DynamicSystemInstallationService/res/values-ur/strings.xml
index 48dddbe..f5e2b74 100644
--- a/packages/DynamicSystemInstallationService/res/values-ur/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ur/strings.xml
@@ -5,7 +5,7 @@
     <string name="notification_install_completed" msgid="6252047868415172643">"ڈائنیمک سسٹم تیار ہے۔ اس کا استعمال شروع کرنے کے لیے، اپنا آلہ ری سٹارٹ کریں۔"</string>
     <string name="notification_install_inprogress" msgid="7383334330065065017">"انسٹال جاری ہے"</string>
     <string name="notification_install_failed" msgid="4066039210317521404">"انسٹال ناکام ہو گیا"</string>
-    <string name="notification_image_validation_failed" msgid="2720357826403917016">"تصویر کی توثیق ناکام ہو گئی۔ انسٹالیشن منسوخ کریں-"</string>
+    <string name="notification_image_validation_failed" msgid="2720357826403917016">"ڈسک امیج کی توثیق ناکام ہو گئی۔ انسٹالیشن منسوخ کریں۔"</string>
     <string name="notification_dynsystem_in_use" msgid="1053194595682188396">"‏فی الحال ہم ایک ڈائنیمک سسٹم چلا رہے ہیں۔ Android کا اصل ورژن استعمال کرنے کے لیے ری سٹارٹ کریں۔"</string>
     <string name="notification_action_cancel" msgid="5929299408545961077">"منسوخ کریں"</string>
     <string name="notification_action_discard" msgid="1817481003134947493">"مسترد کریں"</string>
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ری سٹارٹ کریں"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"مسترد کردہ ڈائنیمک سسٹم"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ڈائنیمک سسٹم کو ری سٹارٹ یا لوڈ نہیں کر سکتے"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-uz/strings.xml b/packages/DynamicSystemInstallationService/res/values-uz/strings.xml
index 3f0227c..3c347e2 100644
--- a/packages/DynamicSystemInstallationService/res/values-uz/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-uz/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Boshidan"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamik tizim bekor qilindi"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dinamik tizim qayta ishga tushmadi yoki yuklanmadi"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-vi/strings.xml b/packages/DynamicSystemInstallationService/res/values-vi/strings.xml
index 18c051c..a93d29e 100644
--- a/packages/DynamicSystemInstallationService/res/values-vi/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-vi/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Khởi động lại"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Đã hủy hệ thống động"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Không thể khởi động lại hoặc tải hệ thống động"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-zh-rCN/strings.xml b/packages/DynamicSystemInstallationService/res/values-zh-rCN/strings.xml
index b41d4e2..c27718e 100644
--- a/packages/DynamicSystemInstallationService/res/values-zh-rCN/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-zh-rCN/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"重启"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"已舍弃动态系统"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"无法重启或加载动态系统"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-zh-rHK/strings.xml b/packages/DynamicSystemInstallationService/res/values-zh-rHK/strings.xml
index c830dae..656c2af 100644
--- a/packages/DynamicSystemInstallationService/res/values-zh-rHK/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-zh-rHK/strings.xml
@@ -5,7 +5,7 @@
     <string name="notification_install_completed" msgid="6252047868415172643">"動態系統已可供使用。如要開始使用,請重新啟動裝置。"</string>
     <string name="notification_install_inprogress" msgid="7383334330065065017">"安裝中"</string>
     <string name="notification_install_failed" msgid="4066039210317521404">"無法安裝"</string>
-    <string name="notification_image_validation_failed" msgid="2720357826403917016">"圖片驗證失敗,系統將取消安裝。"</string>
+    <string name="notification_image_validation_failed" msgid="2720357826403917016">"磁碟影像驗證失敗,系統將取消安裝。"</string>
     <string name="notification_dynsystem_in_use" msgid="1053194595682188396">"系統目前正在執行動態系統。如要使用原本的 Android 版本,請重新啟動裝置。"</string>
     <string name="notification_action_cancel" msgid="5929299408545961077">"取消"</string>
     <string name="notification_action_discard" msgid="1817481003134947493">"捨棄"</string>
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"重新啟動"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"已捨棄動態系統"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"無法重新啟動或載入動態系統"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-zh-rTW/strings.xml b/packages/DynamicSystemInstallationService/res/values-zh-rTW/strings.xml
index e43c0f2..a6f9b56 100644
--- a/packages/DynamicSystemInstallationService/res/values-zh-rTW/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-zh-rTW/strings.xml
@@ -5,7 +5,7 @@
     <string name="notification_install_completed" msgid="6252047868415172643">"動態系統已可供使用。如要開始使用,請重新啟動裝置。"</string>
     <string name="notification_install_inprogress" msgid="7383334330065065017">"安裝中"</string>
     <string name="notification_install_failed" msgid="4066039210317521404">"無法安裝"</string>
-    <string name="notification_image_validation_failed" msgid="2720357826403917016">"圖片驗證失敗,系統將取消安裝作業。"</string>
+    <string name="notification_image_validation_failed" msgid="2720357826403917016">"映像檔驗證失敗,系統將取消安裝作業。"</string>
     <string name="notification_dynsystem_in_use" msgid="1053194595682188396">"系統目前正在執行動態系統。如要使用原本的 Android 版本,請重新啟動裝置。"</string>
     <string name="notification_action_cancel" msgid="5929299408545961077">"取消"</string>
     <string name="notification_action_discard" msgid="1817481003134947493">"捨棄"</string>
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"重新啟動"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"已捨棄動態系統"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"無法重新啟動或載入動態系統"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-zu/strings.xml b/packages/DynamicSystemInstallationService/res/values-zu/strings.xml
index 4a48444..0cf79ba 100644
--- a/packages/DynamicSystemInstallationService/res/values-zu/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-zu/strings.xml
@@ -13,4 +13,6 @@
     <string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Qala kabusha"</string>
     <string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Kulahlwe uhlole olunhlobonhlobo"</string>
     <string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Ayikwazi ukuqalisa kabusha noma ukulayisha uhlole olunhlobonhlobo"</string>
+    <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-es/strings.xml b/packages/SettingsLib/HelpUtils/res/values-es/strings.xml
index 97ff5ef..97e3559 100644
--- a/packages/SettingsLib/HelpUtils/res/values-es/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-es/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="help_feedback_label" msgid="7106780063063027882">"Ayuda y sugerencias"</string>
+    <string name="help_feedback_label" msgid="7106780063063027882">"Ayuda y comentarios"</string>
 </resources>
diff --git a/packages/SettingsProvider/src/android/provider/settings/OWNERS b/packages/SettingsProvider/src/android/provider/settings/OWNERS
index 541dd878..7e7710b 100644
--- a/packages/SettingsProvider/src/android/provider/settings/OWNERS
+++ b/packages/SettingsProvider/src/android/provider/settings/OWNERS
@@ -1,5 +1,4 @@
-# Please reach out to Android B&R when making Settings backup changes
-alsutton@google.com
-nathch@google.com
-rthakohov@google.com
+# Bug component: 656484
+
+include platform/frameworks/base/services/backup:/OWNERS
 
diff --git a/packages/SettingsProvider/test/src/android/provider/OWNERS b/packages/SettingsProvider/test/src/android/provider/OWNERS
index f3241ea..7e7710b 100644
--- a/packages/SettingsProvider/test/src/android/provider/OWNERS
+++ b/packages/SettingsProvider/test/src/android/provider/OWNERS
@@ -1,4 +1,4 @@
-per-file * = *
+# Bug component: 656484
 
-# Please reach out to the Android B&R team for settings backup changes
-per-file SettingsBackupTest.java = alsutton@google.com, nathch@google.com, rthakohov@google.com
+include platform/frameworks/base/services/backup:/OWNERS
+
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index baa266a..2412a32 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -229,6 +229,7 @@
                     Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM,
                     Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR,
                     Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_SV,
+                    Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_VR,
                     Settings.Global.DEVICE_DEMO_MODE,
                     Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS,
                     Settings.Global.BATTERY_SAVER_CONSTANTS,
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 3714db3..939c5f9 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -73,7 +73,7 @@
             android:id="@+id/gradient_clock_view"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textSize="100dp"
+            android:textSize="80dp"
             android:letterSpacing="0.02"
             android:lineSpacingMultiplier=".8"
             android:includeFontPadding="false"
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2e845fb..0e6bc24 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -94,6 +94,7 @@
 import com.android.systemui.DejankUtils;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
+import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
@@ -235,6 +236,7 @@
     private final Context mContext;
     private final boolean mIsPrimaryUser;
     private final boolean mIsAutomotive;
+    private final AuthController mAuthController;
     private final StatusBarStateController mStatusBarStateController;
     HashMap<Integer, SimData> mSimDatas = new HashMap<>();
     HashMap<Integer, ServiceState> mServiceStates = new HashMap<Integer, ServiceState>();
@@ -1581,7 +1583,8 @@
             RingerModeTracker ringerModeTracker,
             @Background Executor backgroundExecutor,
             StatusBarStateController statusBarStateController,
-            LockPatternUtils lockPatternUtils) {
+            LockPatternUtils lockPatternUtils,
+            AuthController authController) {
         mContext = context;
         mSubscriptionManager = SubscriptionManager.from(context);
         mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
@@ -1591,6 +1594,7 @@
         mRingerModeTracker = ringerModeTracker;
         mStatusBarStateController = statusBarStateController;
         mLockPatternUtils = lockPatternUtils;
+        mAuthController = authController;
         dumpManager.registerDumpable(getClass().getName(), this);
 
         mHandler = new Handler(mainLooper) {
@@ -1853,7 +1857,7 @@
 
     private void updateLockScreenMode() {
         mLockScreenMode = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.SHOW_NEW_LOCKSCREEN, 0);
+                Settings.Global.SHOW_NEW_LOCKSCREEN, mAuthController.isUdfpsEnrolled() ? 1 : 0);
     }
 
     private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index d8e94bb..b30103e 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -188,7 +188,7 @@
      * This method is overridden in vendor specific implementation of Sys UI.
      */
     public BackGestureTfClassifierProvider createBackGestureTfClassifierProvider(
-            AssetManager am) {
+            AssetManager am, String modelName) {
         return new BackGestureTfClassifierProvider();
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
index 64a2aca..e40185c 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
@@ -32,6 +32,7 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
@@ -67,7 +68,7 @@
     private final int mTapTimeout = ViewConfiguration.getTapTimeout();
     private final int mTouchSlop;
     private int mMagnificationMode = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
-    private final WindowManager.LayoutParams mParams;
+    private final LayoutParams mParams;
     private boolean mIsVisible = false;
 
     MagnificationModeSwitch(Context context) {
@@ -80,7 +81,7 @@
         mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
         mWindowManager = (WindowManager) mContext.getSystemService(
                 Context.WINDOW_SERVICE);
-        mParams = createLayoutParams();
+        mParams = createLayoutParams(context);
         mImageView = imageView;
         mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
         applyResourcesValues();
@@ -221,11 +222,22 @@
     }
 
     void onConfigurationChanged(int configDiff) {
-        if ((configDiff & ActivityInfo.CONFIG_DENSITY) == 0) {
+        if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
+            applyResourcesValues();
+            mImageView.setImageResource(getIconResId(mMagnificationMode));
             return;
         }
-        applyResourcesValues();
-        mImageView.setImageResource(getIconResId(mMagnificationMode));
+        if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
+            updateAccessibilityWindowTitle();
+            return;
+        }
+    }
+
+    private void updateAccessibilityWindowTitle() {
+        mParams.accessibilityTitle = getAccessibilityWindowTitle(mContext);
+        if (mIsVisible) {
+            mWindowManager.updateViewLayout(mImageView, mParams);
+        }
     }
 
     private void toggleMagnificationMode() {
@@ -261,14 +273,19 @@
                 : R.drawable.ic_open_in_new_fullscreen;
     }
 
-    private static WindowManager.LayoutParams createLayoutParams() {
-        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
-                WindowManager.LayoutParams.WRAP_CONTENT,
-                WindowManager.LayoutParams.WRAP_CONTENT,
-                WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
-                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+    private static LayoutParams createLayoutParams(Context context) {
+        final LayoutParams params = new LayoutParams(
+                LayoutParams.WRAP_CONTENT,
+                LayoutParams.WRAP_CONTENT,
+                LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
+                LayoutParams.FLAG_NOT_FOCUSABLE,
                 PixelFormat.TRANSPARENT);
         params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+        params.accessibilityTitle = getAccessibilityWindowTitle(context);
         return params;
     }
+
+    private static String getAccessibilityWindowTitle(Context context) {
+        return context.getString(com.android.internal.R.string.android_system_label);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index e9e453b..98424be 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -53,7 +53,8 @@
         CommandQueue.Callbacks {
     private static final String TAG = "WindowMagnification";
     private static final int CONFIG_MASK =
-            ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_ORIENTATION;
+            ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_ORIENTATION
+                    | ActivityInfo.CONFIG_LOCALE;
 
     @VisibleForTesting
     protected WindowMagnificationAnimationController mWindowMagnificationAnimationController;
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index 340ca04..fd89baa 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.accessibility;
 
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+import static android.view.WindowManager.LayoutParams;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
 
@@ -254,9 +254,18 @@
             }
         } else if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
             onRotate();
+        } else if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
+            updateAccessibilityWindowTitleIfNeeded();
         }
     }
 
+    private void updateAccessibilityWindowTitleIfNeeded() {
+        if (!isWindowVisible()) return;
+        LayoutParams params = (LayoutParams) mMirrorView.getLayoutParams();
+        params.accessibilityTitle = getAccessibilityWindowTitle();
+        mWm.updateViewLayout(mMirrorView, params);
+    }
+
     /** Handles MirrorWindow position when the navigation bar mode changed. */
     public void onNavigationModeChanged(int mode) {
         mNavBarMode = mode;
@@ -290,8 +299,8 @@
             return;
         }
         // The rect of MirrorView is going to be transformed.
-        WindowManager.LayoutParams params =
-                (WindowManager.LayoutParams) mMirrorView.getLayoutParams();
+        LayoutParams params =
+                (LayoutParams) mMirrorView.getLayoutParams();
         mTmpRect.set(params.x, params.y, params.x + params.width, params.y + params.height);
         final RectF transformedRect = new RectF(mTmpRect);
         matrix.mapRect(transformedRect);
@@ -313,17 +322,18 @@
         int windowWidth = mMagnificationFrame.width() + 2 * mMirrorSurfaceMargin;
         int windowHeight = mMagnificationFrame.height() + 2 * mMirrorSurfaceMargin;
 
-        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+        LayoutParams params = new LayoutParams(
                 windowWidth, windowHeight,
-                WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
-                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+                LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
+                LayoutParams.FLAG_NOT_TOUCH_MODAL
+                        | LayoutParams.FLAG_NOT_FOCUSABLE,
                 PixelFormat.TRANSPARENT);
         params.gravity = Gravity.TOP | Gravity.LEFT;
         params.x = mMagnificationFrame.left - mMirrorSurfaceMargin;
         params.y = mMagnificationFrame.top - mMirrorSurfaceMargin;
-        params.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+        params.layoutInDisplayCutoutMode = LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
         params.setTitle(mContext.getString(R.string.magnification_window_title));
+        params.accessibilityTitle = getAccessibilityWindowTitle();
 
         mMirrorView = LayoutInflater.from(mContext).inflate(R.layout.window_magnifier_view, null);
         mMirrorSurfaceView = mMirrorView.findViewById(R.id.surface_view);
@@ -369,6 +379,10 @@
         return regionInsideDragBorder;
     }
 
+    private String getAccessibilityWindowTitle() {
+        return mResources.getString(com.android.internal.R.string.android_system_label);
+    }
+
     private void showControls() {
         if (mMirrorWindowControl != null) {
             mMirrorWindowControl.showControl();
@@ -432,8 +446,8 @@
         }
         final int maxMirrorViewX = mDisplaySize.x - mMirrorView.getWidth();
         final int maxMirrorViewY = mDisplaySize.y - mMirrorView.getHeight() - mNavGestureHeight;
-        WindowManager.LayoutParams params =
-                (WindowManager.LayoutParams) mMirrorView.getLayoutParams();
+        LayoutParams params =
+                (LayoutParams) mMirrorView.getLayoutParams();
         params.x = mMagnificationFrame.left - mMirrorSurfaceMargin;
         params.y = mMagnificationFrame.top - mMirrorSurfaceMargin;
         // If nav bar mode supports swipe-up gesture, the Y position of mirror view should not
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 874c73b..c72bc25 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -29,6 +29,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Configuration;
+import android.graphics.RectF;
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.IBiometricSysuiReceiver;
@@ -42,6 +43,7 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.MotionEvent;
 import android.view.WindowManager;
 
 import com.android.internal.R;
@@ -243,16 +245,25 @@
     }
 
     /**
+     * @return where the UDFPS exists on the screen in pixels.
+     */
+    public RectF getUdfpsRegion() {
+        return mUdfpsController == null ? null : mUdfpsController.getSensorLocation();
+    }
+
+    /**
      * Requests fingerprint scan.
      *
      * @param screenX X position of long press
      * @param screenY Y position of long press
+     * @param major length of the major axis. See {@link MotionEvent#AXIS_TOOL_MAJOR}.
+     * @param minor length of the minor axis. See {@link MotionEvent#AXIS_TOOL_MINOR}.
      */
-    public void onAodInterrupt(int screenX, int screenY) {
+    public void onAodInterrupt(int screenX, int screenY, float major, float minor) {
         if (mUdfpsController == null) {
             return;
         }
-        mUdfpsController.onAodInterrupt(screenX, screenY);
+        mUdfpsController.onAodInterrupt(screenX, screenY, major, minor);
     }
 
     /**
@@ -475,7 +486,7 @@
    /**
      * Whether the current user has a UDFP enrolled.
      */
-    public boolean hasUdfpsEnrolled() {
+    public boolean isUdfpsEnrolled() {
         // TODO: (b/171392825) right now only checks whether the UDFPS sensor exists on this device
         //  but not whether user has enrolled or not
         return mUdfpsController != null;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 3c2e008..a4b407d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -25,6 +25,7 @@
 import android.content.res.TypedArray;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
+import android.graphics.RectF;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -244,6 +245,13 @@
         mView.dozeTimeTick();
     }
 
+    /**
+     * @return where the UDFPS exists on the screen in pixels.
+     */
+    public RectF getSensorLocation() {
+        return mView.getSensorRect();
+    }
+
     private void setShowOverlay(boolean show) {
         if (show == mIsOverlayRequested) {
             return;
@@ -337,7 +345,7 @@
      * This is intented to be called in response to a sensor that triggers an AOD interrupt for the
      * fingerprint sensor.
      */
-    void onAodInterrupt(int screenX, int screenY) {
+    void onAodInterrupt(int screenX, int screenY, float major, float minor) {
         if (mIsAodInterruptActive) {
             return;
         }
@@ -348,7 +356,7 @@
         mCancelAodTimeoutAction = mFgExecutor.executeDelayed(this::onCancelAodInterrupt,
                 AOD_INTERRUPT_TIMEOUT_MILLIS);
         // using a hard-coded value for major and minor until it is available from the sensor
-        onFingerDown(screenX, screenY, 13.0f, 13.0f);
+        onFingerDown(screenX, screenY, minor, major);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
index 0ed3bda..7edcf66 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
@@ -196,6 +196,10 @@
         canvas.restore();
     }
 
+    RectF getSensorRect() {
+        return new RectF(mSensorRect);
+    }
+
     void setHbmSupported(boolean hbmSupported) {
         mHbmSupported = hbmSupported;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 8220835..f07e5af 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -156,7 +156,7 @@
                         findSensorWithType(config.udfpsLongPressSensorType()),
                         "doze_pulse_on_auth",
                         true /* settingDef */,
-                        authController.hasUdfpsEnrolled() /* configured */,
+                        authController.isUdfpsEnrolled() /* configured */,
                         DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS,
                         true /* reports touch coordinates */,
                         true /* touchscreen */,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index c581e85..58e49f8 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -131,7 +131,10 @@
         DOZING_UPDATE_SENSOR_WAKE_LOCKSCREEN(440),
 
         @UiEvent(doc = "Dozing updated because sensor was tapped.")
-        DOZING_UPDATE_SENSOR_TAP(441);
+        DOZING_UPDATE_SENSOR_TAP(441),
+
+        @UiEvent(doc = "Dozing updated because on display auth was triggered from AOD.")
+        DOZING_UPDATE_AUTH_TRIGGERED(442);
 
         private final int mId;
 
@@ -155,6 +158,7 @@
                 case 7: return DOZING_UPDATE_SENSOR_WAKEUP;
                 case 8: return DOZING_UPDATE_SENSOR_WAKE_LOCKSCREEN;
                 case 9: return DOZING_UPDATE_SENSOR_TAP;
+                case 10: return DOZING_UPDATE_AUTH_TRIGGERED;
                 default: return null;
             }
         }
@@ -289,7 +293,8 @@
                     requestPulse(DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS, true, null);
                     // Since the gesture won't be received by the UDFPS view, manually inject an
                     // event.
-                    mAuthController.onAodInterrupt((int) screenX, (int) screenY);
+                    mAuthController.onAodInterrupt((int) screenX, (int) screenY,
+                            rawValues[2] /* major */, rawValues[3] /* minor */);
                 } else {
                     mDozeHost.extendPulse(pulseReason);
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 1beb875..5eb6687 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -143,6 +143,11 @@
             if (newConfig == null) return
             isRtl = newConfig.layoutDirection == View.LAYOUT_DIRECTION_RTL
         }
+
+        override fun onUiModeChanged() {
+            // Only settings button needs to update for dark theme
+            inflateSettingsButton()
+        }
     }
 
     init {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 6f6ee4c..c6ed9c0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -641,7 +641,8 @@
             // Move to resume key (aka package name) if that key doesn't already exist.
             val resumeAction = getResumeMediaAction(removed.resumeAction!!)
             val updated = removed.copy(token = null, actions = listOf(resumeAction),
-                    actionsToShowInCompact = listOf(0), active = false, resumption = true)
+                    actionsToShowInCompact = listOf(0), active = false, resumption = true,
+                    isClearable = true)
             val pkg = removed.packageName
             val migrate = mediaEntries.put(pkg, updated) == null
             // Notify listeners of "new" controls when migrating or removed and update when not
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 18cc746..f9982d0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -137,7 +137,9 @@
                             && (properties.getKeyset().contains(
                                     SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_THRESHOLD)
                             || properties.getKeyset().contains(
-                                    SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL))) {
+                                    SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL)
+                            || properties.getKeyset().contains(
+                                    SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_NAME))) {
                         updateMLModelState();
                     }
                 }
@@ -483,14 +485,15 @@
     private void updateMLModelState() {
         boolean newState = mIsEnabled && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL, false);
-
         if (newState == mUseMLModel) {
             return;
         }
 
         if (newState) {
+            String mlModelName = DeviceConfig.getString(DeviceConfig.NAMESPACE_SYSTEMUI,
+                    SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_NAME, "backgesture");
             mBackGestureTfClassifierProvider = SystemUIFactory.getInstance()
-                    .createBackGestureTfClassifierProvider(mContext.getAssets());
+                    .createBackGestureTfClassifierProvider(mContext.getAssets(), mlModelName);
             mMLModelThreshold = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_SYSTEMUI,
                     SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_THRESHOLD, 0.9f);
             if (mBackGestureTfClassifierProvider.isActive()) {
@@ -540,21 +543,22 @@
         boolean withinRange = false;
         float results = -1;
 
+         // Disallow if we are in the bottom gesture area
+        if (y >= (mDisplaySize.y - mBottomGestureHeight)) {
+            return false;
+        }
+        // If the point is way too far (twice the margin), it is
+        // not interesting to us for logging purposes, nor we
+        // should process it.  Simply return false and keep
+        // mLogGesture = false.
+        if (x > 2 * (mEdgeWidthLeft + mLeftInset)
+                && x < (mDisplaySize.x - 2 * (mEdgeWidthRight + mRightInset))) {
+            return false;
+        }
+
         if (mUseMLModel &&  (results = getBackGesturePredictionsCategory(x, y)) != -1) {
             withinRange = results == 1 ? true : false;
         } else {
-            // Disallow if we are in the bottom gesture area
-            if (y >= (mDisplaySize.y - mBottomGestureHeight)) {
-                return false;
-            }
-            // If the point is way too far (twice the margin), it is
-            // not interesting to us for logging purposes, nor we
-            // should process it.  Simply return false and keep
-            // mLogGesture = false.
-            if (x > 2 * (mEdgeWidthLeft + mLeftInset)
-                    && x < (mDisplaySize.x - 2 * (mEdgeWidthRight + mRightInset))) {
-                return false;
-            }
             // Denotes whether we should proceed with the gesture.
             // Even if it is false, we may want to log it assuming
             // it is not invalid due to exclusion.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 5cee5bd..2a2a0b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -835,7 +835,13 @@
         if (!mShouldDrawNotificationBackground) {
             return;
         }
-
+        final boolean clearUndershelf = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.SHOW_NEW_NOTIF_DISMISS, 0 /* show background by default */) == 1;
+        if (clearUndershelf) {
+            mBackgroundPaint.setColor(Color.TRANSPARENT);
+            invalidate();
+            return;
+        }
         // Interpolate between semi-transparent notification panel background color
         // and white AOD separator.
         float colorInterpolation = MathUtils.smoothStep(0.4f /* start */, 1f /* end */,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index ef4108b..bd22893 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -86,9 +86,14 @@
     private int mMaxShadeBottom;
 
     /**
-     * Minimum distance from the status bar.
+     * Recommended distance from the status bar without the lock icon.
      */
-    private int mContainerTopPadding;
+    private int mContainerTopPaddingWithoutLockIcon;
+
+    /**
+     * Recommended distance from the status bar with the lock icon.
+     */
+    private int mContainerTopPaddingWithLockIcon;
 
     /**
      * @see NotificationPanelViewController#getExpandedFraction()
@@ -131,24 +136,31 @@
     public void loadDimens(Resources res) {
         mClockNotificationsMargin = res.getDimensionPixelSize(
                 R.dimen.keyguard_clock_notifications_margin);
+
+        mContainerTopPaddingWithoutLockIcon =
+                res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) / 2;
         // Consider the lock icon when determining the minimum top padding between the status bar
         // and top of the clock.
-        mContainerTopPadding = Math.max(res.getDimensionPixelSize(
-                R.dimen.keyguard_clock_top_margin),
-                res.getDimensionPixelSize(R.dimen.keyguard_lock_height)
-                        + res.getDimensionPixelSize(R.dimen.keyguard_lock_padding)
-                        + res.getDimensionPixelSize(R.dimen.keyguard_clock_lock_margin));
+        mContainerTopPaddingWithLockIcon =
+                Math.max(res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin),
+                        res.getDimensionPixelSize(R.dimen.keyguard_lock_height)
+                                + res.getDimensionPixelSize(R.dimen.keyguard_lock_padding)
+                                + res.getDimensionPixelSize(R.dimen.keyguard_clock_lock_margin));
         mBurnInPreventionOffsetX = res.getDimensionPixelSize(
                 R.dimen.burn_in_prevention_offset_x);
         mBurnInPreventionOffsetY = res.getDimensionPixelSize(
                 R.dimen.burn_in_prevention_offset_y);
     }
 
-    public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight,
+    /**
+     * Sets up algorithm values.
+     */
+    public void setup(int statusBarMinHeight, int maxShadeBottom, int notificationStackHeight,
             float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY,
             boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount,
-            boolean bypassEnabled, int unlockedStackScrollerPadding) {
-        mMinTopMargin = minTopMargin + mContainerTopPadding;
+            boolean bypassEnabled, int unlockedStackScrollerPadding, boolean udfpsEnrolled) {
+        mMinTopMargin = statusBarMinHeight + (udfpsEnrolled ? mContainerTopPaddingWithoutLockIcon :
+                mContainerTopPaddingWithLockIcon);
         mMaxShadeBottom = maxShadeBottom;
         mNotificationStackHeight = notificationStackHeight;
         mPanelExpansion = panelExpansion;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
index 77ae059..5e883be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.View.GONE;
+
 import static com.android.systemui.statusbar.phone.LockIcon.STATE_BIOMETRICS_ERROR;
 import static com.android.systemui.statusbar.phone.LockIcon.STATE_LOCKED;
 import static com.android.systemui.statusbar.phone.LockIcon.STATE_LOCK_OPEN;
@@ -37,6 +39,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
+import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dock.DockManager;
@@ -74,6 +77,7 @@
     private final KeyguardStateController mKeyguardStateController;
     private final Resources mResources;
     private final HeadsUpManagerPhone mHeadsUpManagerPhone;
+    private final AuthController mAuthController;
     private boolean mKeyguardShowing;
     private boolean mKeyguardJustShown;
     private boolean mBlockUpdates;
@@ -322,7 +326,8 @@
             @Nullable DockManager dockManager,
             KeyguardStateController keyguardStateController,
             @Main Resources resources,
-            HeadsUpManagerPhone headsUpManagerPhone) {
+            HeadsUpManagerPhone headsUpManagerPhone,
+            AuthController authController) {
         mLockscreenGestureLogger = lockscreenGestureLogger;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mLockPatternUtils = lockPatternUtils;
@@ -337,6 +342,7 @@
         mKeyguardStateController = keyguardStateController;
         mResources = resources;
         mHeadsUpManagerPhone = headsUpManagerPhone;
+        mAuthController = authController;
 
         mKeyguardIndicationController.setLockIconController(this);
     }
@@ -502,6 +508,11 @@
      * @return true if the visibility changed
      */
     private boolean updateIconVisibility() {
+        if (mAuthController.isUdfpsEnrolled()) {
+            boolean changed = mLockIcon.getVisibility() == GONE;
+            mLockIcon.setVisibility(GONE);
+            return changed;
+        }
         boolean onAodOrDocked = mStatusBarStateController.isDozing() || mDocked;
         boolean invisible = onAodOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance;
         boolean fingerprintOrBypass = mFingerprintUnlock
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index b185f48..e9a7132 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -77,6 +77,7 @@
 import com.android.systemui.DejankUtils;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.classifier.Classifier;
 import com.android.systemui.dagger.qualifiers.DisplayId;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -263,6 +264,7 @@
     private final KeyguardBypassController mKeyguardBypassController;
     private final KeyguardUpdateMonitor mUpdateMonitor;
     private final ConversationNotificationManager mConversationNotificationManager;
+    private final AuthController mAuthController;
     private final MediaHierarchyManager mMediaHierarchyManager;
     private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
@@ -516,7 +518,8 @@
             NotificationStackScrollLayoutController notificationStackScrollLayoutController,
             KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
             NotificationGroupManagerLegacy groupManager,
-            NotificationIconAreaController notificationIconAreaController) {
+            NotificationIconAreaController notificationIconAreaController,
+            AuthController authController) {
         super(view, falsingManager, dozeLog, keyguardStateController,
                 (SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
                 latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager);
@@ -581,6 +584,7 @@
         mLockscreenUserManager = notificationLockscreenUserManager;
         mEntryManager = notificationEntryManager;
         mConversationNotificationManager = conversationNotificationManager;
+        mAuthController = authController;
 
         mView.setBackgroundColor(Color.TRANSPARENT);
         OnAttachStateChangeListener onAttachStateChangeListener = new OnAttachStateChangeListener();
@@ -868,7 +872,8 @@
                             - mShelfHeight / 2.0f - mDarkIconSize / 2.0f),
                     clockPreferredY, hasCustomClock(),
                     hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
-                    bypassEnabled, getUnlockedStackScrollerPadding());
+                    bypassEnabled, getUnlockedStackScrollerPadding(),
+                    mAuthController.isUdfpsEnrolled());
             mClockPositionAlgorithm.run(mClockPositionResult);
             mKeyguardStatusViewController.updatePosition(
                     mClockPositionResult.clockX, mClockPositionResult.clockY, animateClock);
@@ -908,6 +913,13 @@
                 mNotificationStackScrollLayoutController.getHeight() - minPadding - shelfSize
                         - Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding)
                         - mKeyguardStatusViewController.getLogoutButtonHeight();
+
+        if (mAuthController.isUdfpsEnrolled()) {
+            availableSpace = mNotificationStackScrollLayoutController.getHeight()
+                    - minPadding - shelfSize
+                    - (mStatusBar.getDisplayHeight() - mAuthController.getUdfpsRegion().top);
+        }
+
         int count = 0;
         ExpandableView previousView = null;
         for (int i = 0; i < mNotificationStackScrollLayoutController.getChildCount(); i++) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index e6479dd..caab2ab 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -79,6 +79,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -156,6 +157,8 @@
     private LiveData<Integer> mRingerModeLiveData;
     @Mock
     private StatusBarStateController mStatusBarStateController;
+    @Mock
+    private AuthController mAuthController;
     // Direct executor
     private Executor mBackgroundExecutor = Runnable::run;
     private TestableLooper mTestableLooper;
@@ -198,6 +201,7 @@
         when(mTelephonyManager.getServiceStateForSubscriber(anyInt()))
                 .thenReturn(new ServiceState());
         when(mLockPatternUtils.getLockSettings()).thenReturn(mLockSettings);
+        when(mAuthController.isUdfpsEnrolled()).thenReturn(false);
         mSpiedContext.addMockSystemService(TrustManager.class, mTrustManager);
         mSpiedContext.addMockSystemService(FingerprintManager.class, mFingerprintManager);
         mSpiedContext.addMockSystemService(BiometricManager.class, mBiometricManager);
@@ -796,7 +800,8 @@
                     TestableLooper.get(KeyguardUpdateMonitorTest.this).getLooper(),
                     mBroadcastDispatcher, mDumpManager,
                     mRingerModeTracker, mBackgroundExecutor,
-                    mStatusBarStateController, mLockPatternUtils);
+                    mStatusBarStateController, mLockPatternUtils,
+                    mAuthController);
             setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
index c923515..a0ae35f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
@@ -287,6 +287,33 @@
         assertShowFadingAnimation(FADE_OUT_ALPHA);
     }
 
+    @Test
+    public void showButton_hasAccessibilityWindowTitle() {
+        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+        ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass(
+                WindowManager.LayoutParams.class);
+        verify(mWindowManager).addView(eq(mSpyImageView), paramsArgumentCaptor.capture());
+        assertEquals(getContext().getResources().getString(
+                com.android.internal.R.string.android_system_label),
+                paramsArgumentCaptor.getValue().accessibilityTitle);
+    }
+
+    @Test
+    public void onLocaleChanged_buttonIsShowing_updateA11yWindowTitle() {
+        final String newA11yWindowTitle = "new a11y window title";
+        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+
+        getContext().getOrCreateTestableResources().addOverride(
+                com.android.internal.R.string.android_system_label, newA11yWindowTitle);
+        mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_LOCALE);
+
+        ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass(
+                WindowManager.LayoutParams.class);
+        verify(mWindowManager).updateViewLayout(eq(mSpyImageView), paramsArgumentCaptor.capture());
+        assertEquals(newA11yWindowTitle, paramsArgumentCaptor.getValue().accessibilityTitle);
+    }
+
     private void assertModeUnchanged(int expectedMode) {
         final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index f1606c5..a39bc70 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -41,6 +41,7 @@
 import android.content.res.Resources;
 import android.os.Handler;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableResources;
 import android.view.Display;
 import android.view.Surface;
 import android.view.SurfaceControl;
@@ -114,8 +115,7 @@
         when(mTransaction.remove(any())).thenReturn(mTransaction);
         when(mTransaction.setGeometry(any(), any(), any(),
                 anyInt())).thenReturn(mTransaction);
-        mResources = Mockito.spy(mContext.getResources());
-        when(mContext.getResources()).thenReturn(mResources);
+        mResources = getContext().getOrCreateTestableResources().getResources();
         mWindowMagnificationController = new WindowMagnificationController(mContext,
                 mHandler, mSfVsyncFrameProvider,
                 mMirrorWindowControl, mTransaction, mWindowMagnifierCallback);
@@ -222,7 +222,6 @@
         assertEquals(Surface.ROTATION_90, mWindowMagnificationController.mRotation);
     }
 
-
     @Test
     public void onDensityChanged_enabled_updateDimensionsAndResetWindowMagnification() {
         mInstrumentation.runOnMainSync(() -> {
@@ -310,4 +309,41 @@
 
         verify(mWindowManager).updateViewLayout(eq(mMirrorView), any());
     }
+
+    @Test
+    public void enableWindowMagnification_hasA11yWindowTitle() {
+        mInstrumentation.runOnMainSync(() -> {
+            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+                    Float.NaN);
+        });
+
+        ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass(
+                WindowManager.LayoutParams.class);
+        verify(mWindowManager).addView(eq(mMirrorView), paramsArgumentCaptor.capture());
+        assertEquals(getContext().getResources().getString(
+                com.android.internal.R.string.android_system_label),
+                paramsArgumentCaptor.getValue().accessibilityTitle);
+    }
+
+    @Test
+    public void onLocaleChanged_enabled_updateA11yWindowTitle() {
+        final String newA11yWindowTitle = "new a11y window title";
+        mInstrumentation.runOnMainSync(() -> {
+            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+                    Float.NaN);
+        });
+        final TestableResources testableResources = getContext().getOrCreateTestableResources();
+        testableResources.addOverride(com.android.internal.R.string.android_system_label,
+                newA11yWindowTitle);
+        when(mContext.getResources()).thenReturn(testableResources.getResources());
+
+        mInstrumentation.runOnMainSync(() -> {
+            mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_LOCALE);
+        });
+
+        ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass(
+                WindowManager.LayoutParams.class);
+        verify(mWindowManager).updateViewLayout(eq(mMirrorView), paramsArgumentCaptor.capture());
+        assertEquals(newA11yWindowTitle, paramsArgumentCaptor.getValue().accessibilityTitle);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 0186d73..42bb005 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -494,8 +494,9 @@
     @Test
     public void testOnAodInterrupt() {
         final int pos = 10;
-        mAuthController.onAodInterrupt(pos, pos);
-        verify(mUdfpsController).onAodInterrupt(eq(pos), eq(pos));
+        final float majorMinor = 5f;
+        mAuthController.onAodInterrupt(pos, pos, majorMinor, majorMinor);
+        verify(mUdfpsController).onAodInterrupt(eq(pos), eq(pos), eq(majorMinor), eq(majorMinor));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index a95396c..82ffd46 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -234,10 +234,10 @@
         mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
         mFgExecutor.runAllReady();
         // WHEN fingerprint is requested because of AOD interrupt
-        mUdfpsController.onAodInterrupt(0, 0);
+        mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
         // THEN the event is passed to the FingerprintManager
         verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0),
-                eq(0), anyFloat(), anyFloat());
+                eq(0), eq(3f) /* minor */, eq(2f) /* major */);
         // AND the scrim and dot is shown
         verify(mUdfpsView).showScrimAndDot();
     }
@@ -247,7 +247,7 @@
         // GIVEN AOD interrupt
         mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
         mFgExecutor.runAllReady();
-        mUdfpsController.onAodInterrupt(0, 0);
+        mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
         // WHEN it is cancelled
         mUdfpsController.onCancelAodInterrupt();
         // THEN the scrim and dot is hidden
@@ -259,7 +259,7 @@
         // GIVEN AOD interrupt
         mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
         mFgExecutor.runAllReady();
-        mUdfpsController.onAodInterrupt(0, 0);
+        mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
         // WHEN it times out
         mFgExecutor.advanceClockToNext();
         mFgExecutor.runAllReady();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 6d87cc3..4bbba56 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -194,10 +194,13 @@
     public void testOnSensor_Fingerprint() {
         final int screenX = 100;
         final int screenY = 100;
+        final float minor = 2f;
+        final float major = 3f;
         final int reason = DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
-        mTriggers.onSensor(reason, screenX, screenY, null);
+        float[] rawValues = new float[]{screenX, screenY, minor, major};
+        mTriggers.onSensor(reason, screenX, screenY, rawValues);
         verify(mHost).extendPulse(reason);
-        verify(mAuthController).onAodInterrupt(eq(screenX), eq(screenY));
+        verify(mAuthController).onAodInterrupt(eq(screenX), eq(screenY), eq(minor), eq(major));
     }
 
     private void waitForSensorManager() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index 2042fab..83ef87a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -384,7 +384,7 @@
         mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
                 mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mPreferredClockY,
                 mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
-                0 /* unlockedStackScrollerPadding */);
+                0 /* unlockedStackScrollerPadding */, false /* udfpsEnrolled */);
         mClockPositionAlgorithm.run(mClockPosition);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
index 06d0331..72a0258 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
@@ -32,6 +32,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -80,6 +81,8 @@
     private Resources mResources;
     @Mock
     private HeadsUpManagerPhone mHeadsUpManagerPhone;
+    @Mock
+    private AuthController mAuthController;
 
     private LockscreenLockIconController mLockIconController;
     private OnAttachStateChangeListener mOnAttachStateChangeListener;
@@ -89,13 +92,14 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
+        when(mAuthController.isUdfpsEnrolled()).thenReturn(false);
         when(mLockIcon.getContext()).thenReturn(mContext);
         mLockIconController = new LockscreenLockIconController(
                 mLockscreenGestureLogger, mKeyguardUpdateMonitor, mLockPatternUtils,
                 mShadeController, mAccessibilityController, mKeyguardIndicationController,
                 mStatusBarStateController, mConfigurationController, mNotificationWakeUpCoordinator,
                 mKeyguardBypassController, mDockManager, mKeyguardStateController, mResources,
-                mHeadsUpManagerPhone);
+                mHeadsUpManagerPhone, mAuthController);
 
         ArgumentCaptor<OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
                 ArgumentCaptor.forClass(OnAttachStateChangeListener.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index cb56f1f..3b123f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -58,6 +58,7 @@
 import com.android.keyguard.dagger.KeyguardStatusViewComponent;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.media.MediaHierarchyManager;
@@ -194,6 +195,8 @@
     private KeyguardStatusViewController mKeyguardStatusViewController;
     @Mock
     private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
+    @Mock
+    private AuthController mAuthController;
 
     private NotificationPanelViewController mNotificationPanelViewController;
     private View.AccessibilityDelegate mAccessibiltyDelegate;
@@ -201,6 +204,7 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
+        when(mAuthController.isUdfpsEnrolled()).thenReturn(false);
         when(mHeadsUpCallback.getContext()).thenReturn(mContext);
         when(mView.getResources()).thenReturn(mResources);
         when(mResources.getConfiguration()).thenReturn(mConfiguration);
@@ -267,7 +271,8 @@
                 mNotificationStackScrollLayoutController,
                 mKeyguardStatusViewComponentFactory,
                 mGroupManager,
-                mNotificationAreaController);
+                mNotificationAreaController,
+                mAuthController);
         mNotificationPanelViewController.initDependencies(
                 mStatusBar,
                 mNotificationShelfController);
diff --git a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-bn/strings.xml
new file mode 100644
index 0000000..3e9c962
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-bn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  ~ Copyright (C) 2020 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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="display_cutout_emulation_overlay" msgid="7305489596221077240">"পাঞ্চ হোল কাট-আউট"</string>
+</resources>
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
index 7c7e742..3c5268c 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -1,7 +1,6 @@
 # Bug component: 656484
 
 aabhinav@google.com
-alsutton@google.com
 bryanmawhinney@google.com
 jstemmer@google.com
 nathch@google.com
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
index f7998ee..15f8c53 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
@@ -46,6 +46,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -81,14 +82,14 @@
  * Supports a single instance of the {@link android.hardware.biometrics.face.V1_0} or
  * its extended minor versions.
  */
-class Face10 implements IHwBinder.DeathRecipient {
+class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
 
     private static final String TAG = "Face10";
     private static final int ENROLL_TIMEOUT_SEC = 75;
     static final String NOTIFICATION_TAG = "FaceService";
     static final int NOTIFICATION_ID = 1;
 
-    @NonNull private final FaceSensorPropertiesInternal mFaceSensorProperties;
+    @NonNull private final FaceSensorPropertiesInternal mSensorProperties;
     @NonNull private final Context mContext;
     @NonNull private final BiometricScheduler mScheduler;
     @NonNull private final Handler mHandler;
@@ -96,23 +97,22 @@
     @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
     @NonNull private final LockoutHalImpl mLockoutTracker;
     @NonNull private final UsageStats mUsageStats;
-    @NonNull private NotificationManager mNotificationManager;
-    private final int mSensorId;
+    @NonNull private final NotificationManager mNotificationManager;
     @NonNull private final Map<Integer, Long> mAuthenticatorIds;
-
     @Nullable private IBiometricsFace mDaemon;
-    private int mCurrentUserId = UserHandle.USER_NULL;
     // If a challenge is generated, keep track of its owner. Since IBiometricsFace@1.0 only
     // supports a single in-flight challenge, we must notify the interrupted owner that its
     // challenge is no longer valid. The interrupted owner will be notified when the interrupter
     // has finished.
     @Nullable private FaceGenerateChallengeClient mCurrentChallengeOwner;
+    private int mCurrentUserId = UserHandle.USER_NULL;
+    private final int mSensorId;
 
     private final UserSwitchObserver mUserSwitchObserver = new SynchronousUserSwitchObserver() {
         @Override
         public void onUserSwitching(int newUserId) {
             scheduleInternalCleanup(newUserId);
-            scheduleGetFeature(new Binder(), newUserId,
+            scheduleGetFeature(mSensorId, new Binder(), newUserId,
                     BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION,
                     null, mContext.getOpPackageName());
         }
@@ -283,7 +283,7 @@
             @BiometricManager.Authenticators.Types int strength,
             @NonNull LockoutResetDispatcher lockoutResetDispatcher,
             boolean supportsSelfIllumination, int maxTemplatesAllowed) {
-        mFaceSensorProperties = new FaceSensorPropertiesInternal(sensorId,
+        mSensorProperties = new FaceSensorPropertiesInternal(sensorId,
                 Utils.authenticatorStrengthToPropertyStrength(strength),
                 maxTemplatesAllowed, false /* supportsFaceDetect */, supportsSelfIllumination);
         mContext = context;
@@ -375,9 +375,10 @@
         if (halId != 0) {
             scheduleLoadAuthenticatorIds();
             scheduleInternalCleanup(ActivityManager.getCurrentUser());
-            scheduleGetFeature(new Binder(), ActivityManager.getCurrentUser(),
-                    BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION,
-                    null, mContext.getOpPackageName());
+            scheduleGetFeature(mSensorId, new Binder(),
+                    ActivityManager.getCurrentUser(),
+                    BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION, null,
+                    mContext.getOpPackageName());
         } else {
             Slog.e(TAG, "Unable to set callback");
             mDaemon = null;
@@ -386,116 +387,39 @@
         return mDaemon;
     }
 
-    @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId) {
+    @Override
+    public boolean containsSensor(int sensorId) {
+        return mSensorId == sensorId;
+    }
+
+    @Override
+    @NonNull
+    public List<FaceSensorPropertiesInternal> getSensorProperties() {
+        final List<FaceSensorPropertiesInternal> properties = new ArrayList<>();
+        properties.add(mSensorProperties);
+        return properties;
+    }
+
+    @Override
+    @NonNull
+    public List<Face> getEnrolledFaces(int sensorId, int userId) {
+        return FaceUtils.getInstance().getBiometricsForUser(mContext, userId);
+    }
+
+    @Override
+    @LockoutTracker.LockoutMode
+    public int getLockoutModeForUser(int sensorId, int userId) {
         return mLockoutTracker.getLockoutModeForUser(userId);
     }
 
-    private void scheduleLoadAuthenticatorIds() {
-        // Note that this can be performed on the scheduler (as opposed to being done immediately
-        // when the HAL is (re)loaded, since
-        // 1) If this is truly the first time it's being performed (e.g. system has just started),
-        //    this will be run very early and way before any applications need to generate keys.
-        // 2) If this is being performed to refresh the authenticatorIds (e.g. HAL crashed and has
-        //    just been reloaded), the framework already has a cache of the authenticatorIds. This
-        //    is safe because authenticatorIds only change when A) new template has been enrolled,
-        //    or B) all templates are removed.
-        mHandler.post(() -> {
-            for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
-                final int targetUserId = user.id;
-                if (!mAuthenticatorIds.containsKey(targetUserId)) {
-                    scheduleUpdateActiveUserWithoutHandler(targetUserId);
-                }
-            }
-        });
+    @Override
+    public long getAuthenticatorId(int sensorId, int userId) {
+        return mAuthenticatorIds.get(userId);
     }
 
-    /**
-     * Schedules the {@link FaceUpdateActiveUserClient} without posting the work onto the
-     * handler. Many/most APIs are user-specific. However, the HAL requires explicit "setActiveUser"
-     * invocation prior to authenticate/enroll/etc. Thus, internally we usually want to schedule
-     * this operation on the same lambda/runnable as those operations so that the ordering is
-     * correct.
-     */
-    private void scheduleUpdateActiveUserWithoutHandler(int targetUserId) {
-        final boolean hasEnrolled = !getEnrolledFaces(targetUserId).isEmpty();
-        final FaceUpdateActiveUserClient client = new FaceUpdateActiveUserClient(mContext,
-                mLazyDaemon, targetUserId, mContext.getOpPackageName(), mSensorId, mCurrentUserId,
-                hasEnrolled, mAuthenticatorIds);
-        mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
-            @Override
-            public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) {
-                if (success) {
-                    mCurrentUserId = targetUserId;
-                }
-            }
-        });
-    }
-
-    void scheduleResetLockout(int userId, @NonNull byte[] hardwareAuthToken) {
-        mHandler.post(() -> {
-            if (getEnrolledFaces(userId).isEmpty()) {
-                Slog.w(TAG, "Ignoring lockout reset, no templates enrolled for user: " + userId);
-                return;
-            }
-
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            final FaceResetLockoutClient client = new FaceResetLockoutClient(mContext,
-                    mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId,
-                    hardwareAuthToken);
-            mScheduler.scheduleClientMonitor(client);
-        });
-    }
-
-    void scheduleSetFeature(@NonNull IBinder token, int userId, int feature, boolean enabled,
-            @NonNull byte[] hardwareAuthToken, @NonNull IFaceServiceReceiver receiver,
-            @NonNull String opPackageName) {
-        mHandler.post(() -> {
-            final List<Face> faces = getEnrolledFaces(userId);
-            if (faces.isEmpty()) {
-                Slog.w(TAG, "Ignoring setFeature, no templates enrolled for user: " + userId);
-                return;
-            }
-
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            final int faceId = faces.get(0).getBiometricId();
-            final FaceSetFeatureClient client = new FaceSetFeatureClient(mContext,
-                    mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId,
-                    opPackageName, mSensorId, feature, enabled, hardwareAuthToken, faceId);
-            mScheduler.scheduleClientMonitor(client);
-        });
-    }
-
-    void scheduleGetFeature(@NonNull IBinder token, int userId, int feature,
-            @Nullable ClientMonitorCallbackConverter listener, @NonNull String opPackageName) {
-        mHandler.post(() -> {
-            final List<Face> faces = getEnrolledFaces(userId);
-            if (faces.isEmpty()) {
-                Slog.w(TAG, "Ignoring getFeature, no templates enrolled for user: " + userId);
-                return;
-            }
-
-            scheduleUpdateActiveUserWithoutHandler(userId);
-
-            final int faceId = faces.get(0).getBiometricId();
-            final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, mLazyDaemon,
-                    token, listener, userId, opPackageName, mSensorId, feature, faceId);
-            mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
-                @Override
-                public void onClientFinished(
-                        @NonNull ClientMonitor<?> clientMonitor, boolean success) {
-                    if (success && feature == BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION) {
-                        final int settingsValue = client.getValue() ? 1 : 0;
-                        Slog.d(TAG, "Updating attention value for user: " + userId
-                                + " to value: " + settingsValue);
-                        Settings.Secure.putIntForUser(mContext.getContentResolver(),
-                                Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
-                                settingsValue, userId);
-                    }
-                }
-            });
-        });
+    @Override
+    public boolean isHardwareDetected(int sensorId) {
+        return getDaemon() != null;
     }
 
     /**
@@ -514,8 +438,9 @@
      * The only case of conflicting challenges is currently resetLockout --> enroll. So, the second
      * option seems better as it prioritizes the new operation, which is user-facing.
      */
-    void scheduleGenerateChallenge(@NonNull IBinder token, @NonNull IFaceServiceReceiver receiver,
-            @NonNull String opPackageName) {
+    @Override
+    public void scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token,
+            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
         mHandler.post(() -> {
             if (mCurrentChallengeOwner != null) {
                 final ClientMonitorCallbackConverter listener =
@@ -550,18 +475,20 @@
         });
     }
 
-    void scheduleRevokeChallenge(@NonNull IBinder token, @NonNull String owner) {
+    @Override
+    public void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token,
+            @NonNull String opPackageName, long challenge) {
         mHandler.post(() -> {
             if (mCurrentChallengeOwner != null &&
-                    !mCurrentChallengeOwner.getOwnerString().contentEquals(owner)) {
-                Slog.e(TAG, "scheduleRevokeChallenge, package: " + owner
+                    !mCurrentChallengeOwner.getOwnerString().contentEquals(opPackageName)) {
+                Slog.e(TAG, "scheduleRevokeChallenge, package: " + opPackageName
                         + " attempting to revoke challenge owned by: "
                         + mCurrentChallengeOwner.getOwnerString());
                 return;
             }
 
             final FaceRevokeChallengeClient client = new FaceRevokeChallengeClient(mContext,
-                    mLazyDaemon, token, owner, mSensorId);
+                    mLazyDaemon, token, opPackageName, mSensorId);
             mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
                 @Override
                 public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor,
@@ -582,13 +509,19 @@
                     final FaceGenerateChallengeClient previousChallengeOwner =
                             mCurrentChallengeOwner.getInterruptedClient();
                     mCurrentChallengeOwner = null;
+
                     Slog.d(TAG, "Previous challenge owner: " + previousChallengeOwner);
                     if (previousChallengeOwner != null) {
-                        try {
-                            previousChallengeOwner.getListener()
-                                    .onChallengeInterruptFinished(mSensorId);
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "Unable to notify interrupt finished", e);
+                        final ClientMonitorCallbackConverter listener =
+                                previousChallengeOwner.getListener();
+                        if (listener == null) {
+                            Slog.w(TAG, "Listener is null");
+                        } else {
+                            try {
+                                listener.onChallengeInterruptFinished(mSensorId);
+                            } catch (RemoteException e) {
+                                Slog.e(TAG, "Unable to notify interrupt finished", e);
+                            }
                         }
                     }
                 }
@@ -596,9 +529,11 @@
         });
     }
 
-    void scheduleEnroll(@NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId,
-            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName,
-            @NonNull int[] disabledFeatures, @Nullable NativeHandle surfaceHandle) {
+    @Override
+    public void scheduleEnroll(int sensorId, @NonNull IBinder token,
+            @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver,
+            @NonNull String opPackageName, @NonNull int[] disabledFeatures,
+            @Nullable NativeHandle surfaceHandle) {
         mHandler.post(() -> {
             scheduleUpdateActiveUserWithoutHandler(userId);
 
@@ -623,15 +558,18 @@
         });
     }
 
-    void cancelEnrollment(@NonNull IBinder token) {
+    @Override
+    public void cancelEnrollment(int sensorId, @NonNull IBinder token) {
         mHandler.post(() -> {
             mScheduler.cancelEnrollment(token);
         });
     }
 
-    void scheduleAuthenticate(@NonNull IBinder token, long operationId, int userId, int cookie,
-            @NonNull ClientMonitorCallbackConverter receiver, @NonNull String opPackageName,
-            boolean restricted, int statsClient) {
+    @Override
+    public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
+            int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
+            @NonNull String opPackageName, boolean restricted, int statsClient,
+            boolean isKeyguard) {
         mHandler.post(() -> {
             scheduleUpdateActiveUserWithoutHandler(userId);
 
@@ -644,19 +582,15 @@
         });
     }
 
-    void startPreparedClient(int cookie) {
-        mHandler.post(() -> {
-            mScheduler.startPreparedClient(cookie);
-        });
-    }
-
-    void cancelAuthentication(@NonNull IBinder token) {
+    @Override
+    public void cancelAuthentication(int sensorId, @NonNull IBinder token) {
         mHandler.post(() -> {
             mScheduler.cancelAuthentication(token);
         });
     }
 
-    void scheduleRemove(@NonNull IBinder token, int faceId, int userId,
+    @Override
+    public void scheduleRemove(int sensorId, @NonNull IBinder token, int faceId, int userId,
             @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
         mHandler.post(() -> {
             scheduleUpdateActiveUserWithoutHandler(userId);
@@ -668,11 +602,82 @@
         });
     }
 
+
+    @Override
+    public void scheduleResetLockout(int sensorId, int userId, @NonNull byte[] hardwareAuthToken) {
+        mHandler.post(() -> {
+            if (getEnrolledFaces(sensorId, userId).isEmpty()) {
+                Slog.w(TAG, "Ignoring lockout reset, no templates enrolled for user: " + userId);
+                return;
+            }
+
+            scheduleUpdateActiveUserWithoutHandler(userId);
+
+            final FaceResetLockoutClient client = new FaceResetLockoutClient(mContext,
+                    mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId,
+                    hardwareAuthToken);
+            mScheduler.scheduleClientMonitor(client);
+        });
+    }
+
+    @Override
+    public void scheduleSetFeature(int sensorId, @NonNull IBinder token, int userId, int feature,
+            boolean enabled, @NonNull byte[] hardwareAuthToken,
+            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
+        mHandler.post(() -> {
+            final List<Face> faces = getEnrolledFaces(sensorId, userId);
+            if (faces.isEmpty()) {
+                Slog.w(TAG, "Ignoring setFeature, no templates enrolled for user: " + userId);
+                return;
+            }
+
+            scheduleUpdateActiveUserWithoutHandler(userId);
+
+            final int faceId = faces.get(0).getBiometricId();
+            final FaceSetFeatureClient client = new FaceSetFeatureClient(mContext,
+                    mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId,
+                    opPackageName, mSensorId, feature, enabled, hardwareAuthToken, faceId);
+            mScheduler.scheduleClientMonitor(client);
+        });
+    }
+
+    @Override
+    public void scheduleGetFeature(int sensorId, @NonNull IBinder token, int userId, int feature,
+            @Nullable ClientMonitorCallbackConverter listener, @NonNull String opPackageName) {
+        mHandler.post(() -> {
+            final List<Face> faces = getEnrolledFaces(sensorId, userId);
+            if (faces.isEmpty()) {
+                Slog.w(TAG, "Ignoring getFeature, no templates enrolled for user: " + userId);
+                return;
+            }
+
+            scheduleUpdateActiveUserWithoutHandler(userId);
+
+            final int faceId = faces.get(0).getBiometricId();
+            final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, mLazyDaemon,
+                    token, listener, userId, opPackageName, mSensorId, feature, faceId);
+            mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+                @Override
+                public void onClientFinished(
+                        @NonNull ClientMonitor<?> clientMonitor, boolean success) {
+                    if (success && feature == BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION) {
+                        final int settingsValue = client.getValue() ? 1 : 0;
+                        Slog.d(TAG, "Updating attention value for user: " + userId
+                                + " to value: " + settingsValue);
+                        Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                                Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
+                                settingsValue, userId);
+                    }
+                }
+            });
+        });
+    }
+
     private void scheduleInternalCleanup(int userId) {
         mHandler.post(() -> {
             scheduleUpdateActiveUserWithoutHandler(userId);
 
-            final List<Face> enrolledList = getEnrolledFaces(userId);
+            final List<Face> enrolledList = getEnrolledFaces(mSensorId, userId);
             final FaceInternalCleanupClient client = new FaceInternalCleanupClient(mContext,
                     mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId, enrolledList,
                     FaceUtils.getInstance(), mAuthenticatorIds);
@@ -680,25 +685,28 @@
         });
     }
 
-    boolean isHardwareDetected() {
-        final IBiometricsFace daemon = getDaemon();
-        return daemon != null;
+    @Override
+    public void scheduleInternalCleanup(int sensorId, int userId) {
+        scheduleInternalCleanup(userId);
     }
 
-    @NonNull
-    FaceSensorPropertiesInternal getFaceSensorProperties() {
-        return mFaceSensorProperties;
+    @Override
+    public void startPreparedClient(int sensorId, int cookie) {
+        mHandler.post(() -> {
+            mScheduler.startPreparedClient(cookie);
+        });
     }
 
-    List<Face> getEnrolledFaces(int userId) {
-        return FaceUtils.getInstance().getBiometricsForUser(mContext, userId);
+    @Override
+    public void dumpProtoState(int sensorId, ProtoOutputStream proto) {
     }
 
-    long getAuthenticatorId(int userId) {
-        return mAuthenticatorIds.get(userId);
+    @Override
+    public void dumpProtoMetrics(int sensorId, FileDescriptor fd) {
     }
 
-    public void dump(@NonNull PrintWriter pw) {
+    @Override
+    public void dumpInternal(int sensorId, PrintWriter pw) {
         PerformanceTracker performanceTracker =
                 PerformanceTracker.getInstanceForSensorId(mSensorId);
 
@@ -733,9 +741,51 @@
         pw.println(dump);
         pw.println("HAL deaths since last reboot: " + performanceTracker.getHALDeathCount());
 
+        mScheduler.dump(pw);
         mUsageStats.print(pw);
     }
 
+    private void scheduleLoadAuthenticatorIds() {
+        // Note that this can be performed on the scheduler (as opposed to being done immediately
+        // when the HAL is (re)loaded, since
+        // 1) If this is truly the first time it's being performed (e.g. system has just started),
+        //    this will be run very early and way before any applications need to generate keys.
+        // 2) If this is being performed to refresh the authenticatorIds (e.g. HAL crashed and has
+        //    just been reloaded), the framework already has a cache of the authenticatorIds. This
+        //    is safe because authenticatorIds only change when A) new template has been enrolled,
+        //    or B) all templates are removed.
+        mHandler.post(() -> {
+            for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
+                final int targetUserId = user.id;
+                if (!mAuthenticatorIds.containsKey(targetUserId)) {
+                    scheduleUpdateActiveUserWithoutHandler(targetUserId);
+                }
+            }
+        });
+    }
+
+    /**
+     * Schedules the {@link FaceUpdateActiveUserClient} without posting the work onto the
+     * handler. Many/most APIs are user-specific. However, the HAL requires explicit "setActiveUser"
+     * invocation prior to authenticate/enroll/etc. Thus, internally we usually want to schedule
+     * this operation on the same lambda/runnable as those operations so that the ordering is
+     * correct.
+     */
+    private void scheduleUpdateActiveUserWithoutHandler(int targetUserId) {
+        final boolean hasEnrolled = !getEnrolledFaces(mSensorId, targetUserId).isEmpty();
+        final FaceUpdateActiveUserClient client = new FaceUpdateActiveUserClient(mContext,
+                mLazyDaemon, targetUserId, mContext.getOpPackageName(), mSensorId, mCurrentUserId,
+                hasEnrolled, mAuthenticatorIds);
+        mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+            @Override
+            public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) {
+                if (success) {
+                    mCurrentUserId = targetUserId;
+                }
+            }
+        });
+    }
+
     public void dumpHal(@NonNull FileDescriptor fd, @NonNull String[] args) {
         // WARNING: CDD restricts image data from leaving TEE unencrypted on
         //          production devices:
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 83f10c8..a298e19 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -16,10 +16,12 @@
 
 package com.android.server.biometrics.sensors.face;
 
+import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.MANAGE_BIOMETRIC;
 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.BiometricsProtoEnums;
@@ -32,7 +34,10 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.NativeHandle;
+import android.os.UserHandle;
+import android.util.Pair;
 import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
 import android.view.Surface;
 
 import com.android.internal.util.DumpUtils;
@@ -46,7 +51,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -58,9 +63,65 @@
 
     protected static final String TAG = "FaceService";
 
-    private Face10 mFace10;
     private final LockoutResetDispatcher mLockoutResetDispatcher;
     private final LockPatternUtils mLockPatternUtils;
+    @NonNull
+    private List<ServiceProvider> mServiceProviders;
+
+    @Nullable
+    private ServiceProvider getProviderForSensor(int sensorId) {
+        for (ServiceProvider provider : mServiceProviders) {
+            if (provider.containsSensor(sensorId)) {
+                return provider;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * For devices with only a single provider, returns that provider. If no providers, or multiple
+     * providers exist, returns null.
+     */
+    @Nullable
+    private Pair<Integer, ServiceProvider> getSingleProvider() {
+        final List<FaceSensorPropertiesInternal> properties = getSensorProperties();
+        if (properties.size() != 1) {
+            Slog.e(TAG, "Multiple sensors found: " + properties.size());
+            return null;
+        }
+
+        // Theoretically we can just return the first provider, but maybe this is easier to
+        // understand.
+        final int sensorId = properties.get(0).sensorId;
+        for (ServiceProvider provider : mServiceProviders) {
+            if (provider.containsSensor(sensorId)) {
+                return new Pair<>(sensorId, provider);
+            }
+        }
+
+        Slog.e(TAG, "Single sensor, but provider not found");
+        return null;
+    }
+
+    @NonNull
+    private List<FaceSensorPropertiesInternal> getSensorProperties() {
+        final List<FaceSensorPropertiesInternal> properties = new ArrayList<>();
+        for (ServiceProvider provider : mServiceProviders) {
+            properties.addAll(provider.getSensorProperties());
+        }
+        return properties;
+    }
+
+    @NonNull
+    private List<Face> getEnrolledFaces(int userId, String opPackageName) {
+        final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+        if (provider == null) {
+            Slog.w(TAG, "Null provider for getEnrolledFaces, caller: " + opPackageName);
+            return Collections.emptyList();
+        }
+
+        return provider.second.getEnrolledFaces(provider.first, userId);
+    }
 
     /**
      * Receives the incoming binder calls from FaceManager.
@@ -69,13 +130,10 @@
         @Override // Binder call
         public List<FaceSensorPropertiesInternal> getSensorPropertiesInternal(
                 String opPackageName) {
-            Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
+            Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
 
-            final List<FaceSensorPropertiesInternal> properties = new ArrayList<>();
-
-            if (mFace10 != null) {
-                properties.add(mFace10.getFaceSensorProperties());
-            }
+            final List<FaceSensorPropertiesInternal> properties =
+                    FaceService.this.getSensorProperties();
 
             Slog.d(TAG, "Retrieved sensor properties for: " + opPackageName
                     + ", sensors: " + properties.size());
@@ -83,27 +141,31 @@
         }
 
         @Override // Binder call
-        public void generateChallenge(IBinder token, int sensorId, IFaceServiceReceiver receiver,
-                String opPackageName) {
+        public void generateChallenge(IBinder token, int sensorId, int userId,
+                IFaceServiceReceiver receiver, String opPackageName) {
             Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
-            if (sensorId == mFace10.getFaceSensorProperties().sensorId) {
-                mFace10.scheduleGenerateChallenge(token, receiver, opPackageName);
+
+            final ServiceProvider provider = getProviderForSensor(sensorId);
+            if (provider == null) {
+                Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId);
                 return;
             }
 
-            Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId);
+            provider.scheduleGenerateChallenge(sensorId, userId, token, receiver, opPackageName);
         }
 
         @Override // Binder call
-        public void revokeChallenge(IBinder token, int sensorId, String owner) {
+        public void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName,
+                long challenge) {
             Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
 
-            if (sensorId == mFace10.getFaceSensorProperties().sensorId) {
-                mFace10.scheduleRevokeChallenge(token, owner);
+            final ServiceProvider provider = getProviderForSensor(sensorId);
+            if (provider == null) {
+                Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId);
                 return;
             }
 
-            Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId);
+            provider.scheduleRevokeChallenge(sensorId, userId, token, opPackageName, challenge);
         }
 
         @Override // Binder call
@@ -111,8 +173,16 @@
                 final IFaceServiceReceiver receiver, final String opPackageName,
                 final int[] disabledFeatures, Surface surface) {
             Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
-            mFace10.scheduleEnroll(token, hardwareAuthToken, userId, receiver, opPackageName,
-                    disabledFeatures, convertSurfaceToNativeHandle(surface));
+
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for enroll");
+                return;
+            }
+
+            provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
+                    receiver, opPackageName, disabledFeatures,
+                    convertSurfaceToNativeHandle(surface));
         }
 
         @Override // Binder call
@@ -126,7 +196,14 @@
         @Override // Binder call
         public void cancelEnrollment(final IBinder token) {
             Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
-            mFace10.cancelEnrollment(token);
+
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for cancelEnrollment");
+                return;
+            }
+
+            provider.second.cancelEnrollment(provider.first, token);
         }
 
         @Override // Binder call
@@ -141,9 +218,21 @@
             final int statsClient = Utils.isKeyguard(getContext(), opPackageName)
                     ? BiometricsProtoEnums.CLIENT_KEYGUARD
                     : BiometricsProtoEnums.CLIENT_UNKNOWN;
-            mFace10.scheduleAuthenticate(token, operationId, userId, 0 /* cookie */,
+
+            // Keyguard check must be done on the caller's binder identity, since it also checks
+            // permission.
+            final boolean isKeyguard = Utils.isKeyguard(getContext(), opPackageName);
+
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for authenticate");
+                return;
+            }
+
+            provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
+                    0 /* cookie */,
                     new ClientMonitorCallbackConverter(receiver), opPackageName, restricted,
-                    statsClient);
+                    statsClient, isKeyguard);
         }
 
         @Override // Binder call
@@ -172,22 +261,42 @@
                 int callingUserId) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
 
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for prepareForAuthentication");
+                return;
+            }
+
             final boolean restricted = true; // BiometricPrompt is always restricted
-            mFace10.scheduleAuthenticate(token, operationId, userId, cookie,
-                    new ClientMonitorCallbackConverter(sensorReceiver), opPackageName,
-                    restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT);
+            provider.second.scheduleAuthenticate(provider.first, token, operationId, userId, cookie,
+                    new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted,
+                    BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, false /* isKeyguard */);
         }
 
         @Override // Binder call
         public void startPreparedClient(int cookie) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-            mFace10.startPreparedClient(cookie);
+
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for startPreparedClient");
+                return;
+            }
+
+            provider.second.startPreparedClient(provider.first, cookie);
         }
 
         @Override // Binder call
         public void cancelAuthentication(final IBinder token, final String opPackageName) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-            mFace10.cancelAuthentication(token);
+
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for cancelAuthentication");
+                return;
+            }
+
+            provider.second.cancelAuthentication(provider.first, token);
         }
 
         @Override // Binder call
@@ -206,14 +315,29 @@
         public void cancelAuthenticationFromService(final IBinder token, final String opPackageName,
                 int callingUid, int callingPid, int callingUserId) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-            mFace10.cancelAuthentication(token);
+
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for cancelAuthenticationFromService");
+                return;
+            }
+
+            provider.second.cancelAuthentication(provider.first, token);
         }
 
         @Override // Binder call
         public void remove(final IBinder token, final int faceId, final int userId,
                 final IFaceServiceReceiver receiver, final String opPackageName) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-            mFace10.scheduleRemove(token, faceId, userId, receiver, opPackageName);
+
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for remove");
+                return;
+            }
+
+            provider.second.scheduleRemove(provider.first, token, faceId, userId, receiver,
+                    opPackageName);
         }
 
         @Override
@@ -231,10 +355,28 @@
 
             final long ident = Binder.clearCallingIdentity();
             try {
-                if (args.length > 1 && "--hal".equals(args[0])) {
-                    mFace10.dumpHal(fd, Arrays.copyOfRange(args, 1, args.length, args.getClass()));
+                if (args.length > 1 && "--proto".equals(args[0]) && "--state".equals(args[1])) {
+                    final ProtoOutputStream proto = new ProtoOutputStream(fd);
+                    for (ServiceProvider provider : mServiceProviders) {
+                        for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
+                            provider.dumpProtoState(props.sensorId, proto);
+                        }
+                    }
+                    proto.flush();
+                } else if (args.length > 0 && "--proto".equals(args[0])) {
+                    for (ServiceProvider provider : mServiceProviders) {
+                        for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
+                            provider.dumpProtoMetrics(props.sensorId, fd);
+                        }
+                    }
                 } else {
-                    mFace10.dump(pw);
+                    for (ServiceProvider provider : mServiceProviders) {
+                        for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
+                            pw.println("Dumping for sensorId: " + props.sensorId
+                                    + ", provider: " + provider.getClass().getSimpleName());
+                            provider.dumpInternal(props.sensorId, pw);
+                        }
+                    }
                 }
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -244,13 +386,15 @@
         @Override // Binder call
         public boolean isHardwareDetected(String opPackageName) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-            if (mFace10 == null) {
-                Slog.wtf(TAG, "No HAL, caller: " + opPackageName);
-                return false;
-            }
+
             final long token = Binder.clearCallingIdentity();
             try {
-                return mFace10.isHardwareDetected();
+                final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+                if (provider == null) {
+                    Slog.w(TAG, "Null provider for isHardwareDetected, caller: " + opPackageName);
+                    return false;
+                }
+                return provider.second.isHardwareDetected(provider.first);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -259,25 +403,50 @@
         @Override // Binder call
         public List<Face> getEnrolledFaces(int userId, String opPackageName) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-            return mFace10.getEnrolledFaces(userId);
+
+            if (userId != UserHandle.getCallingUserId()) {
+                Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS);
+            }
+
+            return FaceService.this.getEnrolledFaces(userId, opPackageName);
         }
 
         @Override // Binder call
         public boolean hasEnrolledFaces(int userId, String opPackageName) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-            return !mFace10.getEnrolledFaces(userId).isEmpty();
+
+            if (userId != UserHandle.getCallingUserId()) {
+                Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS);
+            }
+
+            return !FaceService.this.getEnrolledFaces(userId, opPackageName).isEmpty();
         }
 
-        @Override
-        public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId) {
+        @Override // Binder call
+        @LockoutTracker.LockoutMode
+        public int getLockoutModeForUser(int userId) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-            return mFace10.getLockoutModeForUser(userId);
+
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for getLockoutModeForUser");
+                return LockoutTracker.LOCKOUT_NONE;
+            }
+
+            return provider.second.getLockoutModeForUser(provider.first, userId);
         }
 
         @Override // Binder call
         public long getAuthenticatorId(int userId) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-            return mFace10.getAuthenticatorId(userId);
+
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for getAuthenticatorId");
+                return 0;
+            }
+
+            return provider.second.getAuthenticatorId(provider.first, userId);
         }
 
         @Override // Binder call
@@ -285,12 +454,13 @@
                 String opPackageName) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
 
-            if (sensorId == mFace10.getFaceSensorProperties().sensorId) {
-                mFace10.scheduleResetLockout(userId, hardwareAuthToken);
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for resetLockout, caller: " + opPackageName);
                 return;
             }
 
-            Slog.w(TAG, "No matching sensor for resetLockout, sensorId: " + sensorId);
+            provider.second.scheduleResetLockout(provider.first, userId, hardwareAuthToken);
         }
 
         @Override
@@ -298,15 +468,29 @@
                 final byte[] hardwareAuthToken, IFaceServiceReceiver receiver,
                 final String opPackageName) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-            mFace10.scheduleSetFeature(token, userId, feature, enabled, hardwareAuthToken, receiver,
-                    opPackageName);
+
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for setFeature");
+                return;
+            }
+
+            provider.second.scheduleSetFeature(provider.first, token, userId, feature, enabled,
+                    hardwareAuthToken, receiver, opPackageName);
         }
 
         @Override
         public void getFeature(final IBinder token, int userId, int feature,
                 IFaceServiceReceiver receiver, final String opPackageName) {
             Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
-            mFace10.scheduleGetFeature(token, userId, feature,
+
+            final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+            if (provider == null) {
+                Slog.w(TAG, "Null provider for getFeature");
+                return;
+            }
+
+            provider.second.scheduleGetFeature(provider.first, token, userId, feature,
                     new ClientMonitorCallbackConverter(receiver), opPackageName);
         }
 
@@ -314,7 +498,8 @@
         public void initializeConfiguration(int sensorId,
                 @BiometricManager.Authenticators.Types int strength) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-            mFace10 = new Face10(getContext(), sensorId, strength, mLockoutResetDispatcher);
+            mServiceProviders.add(
+                    new Face10(getContext(), sensorId, strength, mLockoutResetDispatcher));
         }
     }
 
@@ -322,6 +507,7 @@
         super(context);
         mLockoutResetDispatcher = new LockoutResetDispatcher(context);
         mLockPatternUtils = new LockPatternUtils(context);
+        mServiceProviders = new ArrayList<>();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
new file mode 100644
index 0000000..e3fb750
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 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.biometrics.sensors.face;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.face.Face;
+import android.hardware.face.FaceSensorPropertiesInternal;
+import android.hardware.face.IFaceServiceReceiver;
+import android.os.IBinder;
+import android.os.NativeHandle;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.LockoutTracker;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Superset of features across all the face HAL interfaces that are available to the framework. This
+ * is more or less mapped to the public and private APIs that {@link FaceManager} provides, and
+ * is used at the system server layer to provide easy mapping between requests and providers.
+ *
+ * Note that providers support both single-sensor and multi-sensor HALs. In either case,
+ * {@link FaceService} must ensure that providers are only requested to perform operations
+ * on sensors that they own.
+ *
+ * For methods other than {@link #containsSensor(int)}, the caller must ensure that the sensorId
+ * is supported by the provider. For example:
+ * if (serviceProvider.containsSensor(sensorId)) {
+ * serviceProvider.operation(sensorId, ...);
+ * }
+ *
+ * For operations that are supported by some providers but not others, clients are required
+ * to check (e.g. via {@link FaceManager#getSensorPropertiesInternal()}) that the code path isn't
+ * taken. ServiceProviders will provide a no-op for unsupported operations to fail safely.
+ */
+public interface ServiceProvider {
+    /**
+     * Checks if the specified sensor is owned by this provider.
+     */
+    boolean containsSensor(int sensorId);
+
+    @NonNull
+    List<FaceSensorPropertiesInternal> getSensorProperties();
+
+    @NonNull
+    List<Face> getEnrolledFaces(int sensorId, int userId);
+
+    @LockoutTracker.LockoutMode
+    int getLockoutModeForUser(int sensorId, int userId);
+
+    long getAuthenticatorId(int sensorId, int userId);
+
+    boolean isHardwareDetected(int sensorId);
+
+    void scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token,
+            @NonNull IFaceServiceReceiver receiver, String opPackageName);
+
+    void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token,
+            @NonNull String opPackageName, long challenge);
+
+    void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken,
+            int userId, @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName,
+            @NonNull int[] disabledFeatures, @Nullable NativeHandle surfaceHandle);
+
+    void cancelEnrollment(int sensorId, @NonNull IBinder token);
+
+    void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
+            int cookie, @NonNull ClientMonitorCallbackConverter callback,
+            @NonNull String opPackageName, boolean restricted, int statsClient, boolean isKeyguard);
+
+
+    void cancelAuthentication(int sensorId, @NonNull IBinder token);
+
+    void scheduleRemove(int sensorId, @NonNull IBinder token, int faceId, int userId,
+            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName);
+
+    void scheduleResetLockout(int sensorId, int userId, @NonNull byte[] hardwareAuthToken);
+
+    void scheduleSetFeature(int sensorId, @NonNull IBinder token, int userId, int feature,
+            boolean enabled, @NonNull byte[] hardwareAuthToken,
+            @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName);
+
+    void scheduleGetFeature(int sensorId, @NonNull IBinder token, int userId, int feature,
+            @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName);
+
+    void startPreparedClient(int sensorId, int cookie);
+
+    void scheduleInternalCleanup(int sensorId, int userId);
+
+    void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto);
+
+    void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd);
+
+    void dumpInternal(int sensorId, @NonNull PrintWriter pw);
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index c88247f..265ba05 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -469,6 +469,27 @@
         }
 
         @Override // Binder call
+        public boolean hasEnrolledTemplatesForAnySensor(int userId,
+                @NonNull List<FingerprintSensorPropertiesInternal> sensors,
+                @NonNull String opPackageName) {
+            Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
+
+            for (FingerprintSensorPropertiesInternal prop : sensors) {
+                final ServiceProvider provider = getProviderForSensor(prop.sensorId);
+                if (provider == null) {
+                    Slog.w(TAG, "Null provider for sensorId: " + prop.sensorId
+                            + ", caller: " + opPackageName);
+                    continue;
+                }
+
+                if (!provider.getEnrolledFingerprints(prop.sensorId, userId).isEmpty()) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override // Binder call
         public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId) {
             Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index a806e3f..8c766d6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -646,8 +646,7 @@
 
     @Override
     public boolean isHardwareDetected(int sensorId) {
-        final IBiometricsFingerprint daemon = getDaemon();
-        return daemon != null;
+        return getDaemon() != null;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 88867fc..a4ae9c8 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.camera;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
@@ -39,6 +40,7 @@
 import android.util.ArraySet;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.FrameworkStatsLog;
@@ -48,6 +50,8 @@
 import com.android.server.SystemService.TargetUser;
 import com.android.server.wm.WindowManagerInternal;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -79,10 +83,19 @@
 
     // Handler message codes
     private static final int MSG_SWITCH_USER = 1;
+    private static final int MSG_NOTIFY_DEVICE_STATE = 2;
 
     private static final int RETRY_DELAY_TIME = 20; //ms
     private static final int RETRY_TIMES = 60;
 
+    @IntDef(flag = true, prefix = { "DEVICE_STATE_" }, value = {
+            ICameraService.DEVICE_STATE_BACK_COVERED,
+            ICameraService.DEVICE_STATE_FRONT_COVERED,
+            ICameraService.DEVICE_STATE_FOLDED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface DeviceStateFlags {}
+
     // Maximum entries to keep in usage history before dumping out
     private static final int MAX_USAGE_HISTORY = 100;
 
@@ -94,6 +107,15 @@
     private final Object mLock = new Object();
     private Set<Integer> mEnabledCameraUsers;
     private int mLastUser;
+    // The current set of device state flags. May be different from mLastReportedDeviceState if the
+    // native camera service has not been notified of the change.
+    @GuardedBy("mLock")
+    @DeviceStateFlags
+    private int mDeviceState;
+    // The most recent device state flags reported to the native camera server.
+    @GuardedBy("mLock")
+    @DeviceStateFlags
+    private int mLastReportedDeviceState;
 
     private ICameraService mCameraServiceRaw;
 
@@ -185,6 +207,7 @@
                 return;
             }
             notifySwitchWithRetries(RETRY_TIMES);
+            notifyDeviceStateWithRetries(RETRY_TIMES);
         }
 
         @Override
@@ -218,12 +241,55 @@
         mLogWriterService.allowCoreThreadTimeOut(true);
     }
 
+    /**
+     * Sets the device state bits set within {@code deviceStateFlags} leaving all other bits the
+     * same.
+     * <p>
+     * Calling requires permission {@link android.Manifest.permission#CAMERA_SEND_SYSTEM_EVENTS}.
+     *
+     * @param deviceStateFlags a bitmask of the device state bits that should be set.
+     *
+     * @see #clearDeviceStateFlags(int)
+     */
+    public void setDeviceStateFlags(@DeviceStateFlags int deviceStateFlags) {
+        synchronized (mLock) {
+            mHandler.removeMessages(MSG_NOTIFY_DEVICE_STATE);
+            mDeviceState |= deviceStateFlags;
+            if (mDeviceState != mLastReportedDeviceState) {
+                notifyDeviceStateWithRetriesLocked(RETRY_TIMES);
+            }
+        }
+    }
+
+    /**
+     * Clears the device state bits set within {@code deviceStateFlags} leaving all other bits the
+     * same.
+     * <p>
+     * Calling requires permission {@link android.Manifest.permission#CAMERA_SEND_SYSTEM_EVENTS}.
+     *
+     * @param deviceStateFlags a bitmask of the device state bits that should be cleared.
+     *
+     * @see #setDeviceStateFlags(int)
+     */
+    public void clearDeviceStateFlags(@DeviceStateFlags int deviceStateFlags) {
+        synchronized (mLock) {
+            mHandler.removeMessages(MSG_NOTIFY_DEVICE_STATE);
+            mDeviceState &= ~deviceStateFlags;
+            if (mDeviceState != mLastReportedDeviceState) {
+                notifyDeviceStateWithRetriesLocked(RETRY_TIMES);
+            }
+        }
+    }
+
     @Override
     public boolean handleMessage(Message msg) {
         switch(msg.what) {
             case MSG_SWITCH_USER: {
                 notifySwitchWithRetries(msg.arg1);
             } break;
+            case MSG_NOTIFY_DEVICE_STATE: {
+                notifyDeviceStateWithRetries(msg.arg1);
+            } break;
             default: {
                 Slog.e(TAG, "CameraServiceProxy error, invalid message: " + msg.what);
             } break;
@@ -386,6 +452,25 @@
         }
     }
 
+    @Nullable
+    private ICameraService getCameraServiceRawLocked() {
+        if (mCameraServiceRaw == null) {
+            IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
+            if (cameraServiceBinder == null) {
+                return null;
+            }
+            try {
+                cameraServiceBinder.linkToDeath(this, /*flags*/ 0);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Could not link to death of native camera service");
+                return null;
+            }
+
+            mCameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
+        }
+        return mCameraServiceRaw;
+    }
+
     private void switchUserLocked(int userHandle) {
         Set<Integer> currentUserHandles = getEnabledUserHandles(userHandle);
         mLastUser = userHandle;
@@ -431,20 +516,10 @@
     private boolean notifyCameraserverLocked(int eventType, Set<Integer> updatedUserHandles) {
         // Forward the user switch event to the native camera service running in the cameraserver
         // process.
-        if (mCameraServiceRaw == null) {
-            IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
-            if (cameraServiceBinder == null) {
-                Slog.w(TAG, "Could not notify cameraserver, camera service not available.");
-                return false; // Camera service not active, cannot evict user clients.
-            }
-            try {
-                cameraServiceBinder.linkToDeath(this, /*flags*/ 0);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Could not link to death of native camera service");
-                return false;
-            }
-
-            mCameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
+        ICameraService cameraService = getCameraServiceRawLocked();
+        if (cameraService == null) {
+            Slog.w(TAG, "Could not notify cameraserver, camera service not available.");
+            return false;
         }
 
         try {
@@ -457,6 +532,43 @@
         return true;
     }
 
+    private void notifyDeviceStateWithRetries(int retries) {
+        synchronized (mLock) {
+            notifyDeviceStateWithRetriesLocked(retries);
+        }
+    }
+
+    private void notifyDeviceStateWithRetriesLocked(int retries) {
+        if (notifyDeviceStateChangeLocked(mDeviceState)) {
+            return;
+        }
+        if (retries <= 0) {
+            return;
+        }
+        Slog.i(TAG, "Could not notify camera service of device state change, retrying...");
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_NOTIFY_DEVICE_STATE, retries - 1,
+                0, null), RETRY_DELAY_TIME);
+    }
+
+    private boolean notifyDeviceStateChangeLocked(@DeviceStateFlags int deviceState) {
+        // Forward the state to the native camera service running in the cameraserver process.
+        ICameraService cameraService = getCameraServiceRawLocked();
+        if (cameraService == null) {
+            Slog.w(TAG, "Could not notify cameraserver, camera service not available.");
+            return false;
+        }
+
+        try {
+            mCameraServiceRaw.notifyDeviceStateChange(deviceState);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Could not notify cameraserver, remote exception: " + e);
+            // Not much we can do if camera service is dead.
+            return false;
+        }
+        mLastReportedDeviceState = deviceState;
+        return true;
+    }
+
     private void updateActivityCount(String cameraId, int newCameraState, int facing,
             String clientName, int apiLevel) {
         synchronized(mLock) {
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index bc3bff1..ff31931 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -18,7 +18,7 @@
 
 import android.annotation.Nullable;
 import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.EnabledSince;
 import android.content.pm.ApplicationInfo;
 
 import com.android.internal.compat.CompatibilityChangeInfo;
@@ -43,8 +43,8 @@
      * A change ID to be used only in the CTS test for this SystemApi
      */
     @ChangeId
-    @EnabledAfter(targetSdkVersion = 1234) // Needs to be > test APK targetSdkVersion.
-    private static final long CTS_SYSTEM_API_CHANGEID = 149391281; // This is a bug id.
+    @EnabledSince(targetSdkVersion = 1235) // Needs to be > test APK targetSdkVersion.
+    static final long CTS_SYSTEM_API_CHANGEID = 149391281; // This is a bug id.
 
     /**
      * Callback listener for when compat changes are updated for a package.
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index e4f52f1..77d5411 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -381,6 +381,9 @@
         if (change.getLoggingOnly()) {
             return false;
         }
+        if (change.getId() == CompatChange.CTS_SYSTEM_API_CHANGEID) {
+            return false;
+        }
         if (change.getEnableSinceTargetSdk() > 0) {
             if (change.getEnableSinceTargetSdk() < sMinTargetSdk
                     || change.getEnableSinceTargetSdk() > sMaxTargetSdk) {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 6a3e7b7..b10cd12 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -227,8 +227,35 @@
     private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
             new CopyOnWriteArrayList<DisplayTransactionListener>();
 
-    // Display power controller.
-    private DisplayPowerController mDisplayPowerController;
+    /** All {@link DisplayPowerController}s indexed by {@link LogicalDisplay} ID. */
+    private final SparseArray<DisplayPowerController> mDisplayPowerControllers =
+            new SparseArray<>();
+
+    /** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */
+    private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
+        @Override
+        public void requestDisplayState(int displayId, int state, float brightness) {
+            // The order of operations is important for legacy reasons.
+            if (state == Display.STATE_OFF) {
+                requestGlobalDisplayStateInternal(state, brightness);
+            }
+
+            mDisplayPowerCallbacks.onDisplayStateChange(state);
+
+            if (state != Display.STATE_OFF) {
+                requestGlobalDisplayStateInternal(state, brightness);
+            }
+        }
+    };
+
+    /**
+     * Used to inform {@link com.android.server.power.PowerManagerService} of changes to display
+     * state.
+     */
+    private DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks;
+
+    /** The {@link Handler} used by all {@link DisplayPowerController}s. */
+    private Handler mPowerHandler;
 
     // The overall display state, independent of changes that might influence one
     // display or another in particular.
@@ -419,14 +446,16 @@
         final int newUserId = to.getUserIdentifier();
         final int userSerial = getUserManager().getUserSerialNumber(newUserId);
         synchronized (mSyncRoot) {
+            final DisplayPowerController displayPowerController = mDisplayPowerControllers.get(
+                    Display.DEFAULT_DISPLAY);
             if (mCurrentUserId != newUserId) {
                 mCurrentUserId = newUserId;
                 BrightnessConfiguration config =
                         mPersistentDataStore.getBrightnessConfiguration(userSerial);
-                mDisplayPowerController.setBrightnessConfiguration(config);
+                displayPowerController.setBrightnessConfiguration(config);
                 handleSettingsChange();
             }
-            mDisplayPowerController.onSwitchUser(newUserId);
+            displayPowerController.onSwitchUser(newUserId);
         }
     }
 
@@ -957,6 +986,7 @@
             recordStableDisplayStatsIfNeededLocked(display);
             recordTopInsetLocked(display);
         }
+        addDisplayPowerControllerLocked(displayId);
 
         DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
 
@@ -990,6 +1020,7 @@
 
     private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) {
         final int displayId = display.getDisplayIdLocked();
+        mDisplayPowerControllers.delete(displayId);
         DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
         sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
         scheduleTraversalLocked(false);
@@ -1111,7 +1142,7 @@
                 mPersistentDataStore.saveIfNeeded();
             }
             if (userId == mCurrentUserId) {
-                mDisplayPowerController.setBrightnessConfiguration(c);
+                mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY).setBrightnessConfiguration(c);
             }
         }
     }
@@ -1143,7 +1174,8 @@
             final int userSerial = getUserManager().getUserSerialNumber(mCurrentUserId);
             BrightnessConfiguration config =
                     mPersistentDataStore.getBrightnessConfiguration(userSerial);
-            mDisplayPowerController.setBrightnessConfiguration(config);
+            mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY).setBrightnessConfiguration(
+                    config);
         }
     }
 
@@ -1350,25 +1382,31 @@
     }
 
     void setAutoBrightnessLoggingEnabled(boolean enabled) {
-        if (mDisplayPowerController != null) {
-            synchronized (mSyncRoot) {
-                mDisplayPowerController.setAutoBrightnessLoggingEnabled(enabled);
+        synchronized (mSyncRoot) {
+            final DisplayPowerController displayPowerController = mDisplayPowerControllers.get(
+                    Display.DEFAULT_DISPLAY);
+            if (displayPowerController != null) {
+                displayPowerController.setAutoBrightnessLoggingEnabled(enabled);
             }
         }
     }
 
     void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
-        if (mDisplayPowerController != null) {
-            synchronized (mSyncRoot) {
-                mDisplayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled);
+        synchronized (mSyncRoot) {
+            final DisplayPowerController displayPowerController = mDisplayPowerControllers.get(
+                    Display.DEFAULT_DISPLAY);
+            if (displayPowerController != null) {
+                displayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled);
             }
         }
     }
 
     void setAmbientColorTemperatureOverride(float cct) {
-        if (mDisplayPowerController != null) {
-            synchronized (mSyncRoot) {
-                mDisplayPowerController.setAmbientColorTemperatureOverride(cct);
+        synchronized (mSyncRoot) {
+            final DisplayPowerController displayPowerController = mDisplayPowerControllers.get(
+                    Display.DEFAULT_DISPLAY);
+            if (displayPowerController != null) {
+                displayPowerController.setAmbientColorTemperatureOverride(cct);
             }
         }
     }
@@ -1594,8 +1632,11 @@
                         + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
             }
 
-            if (mDisplayPowerController != null) {
-                mDisplayPowerController.dump(pw);
+            final int displayPowerControllerCount = mDisplayPowerControllers.size();
+            pw.println();
+            pw.println("Display Power Controllers: size=" + displayPowerControllerCount);
+            for (int i = 0; i < displayPowerControllerCount; i++) {
+                mDisplayPowerControllers.valueAt(i).dump(pw);
             }
 
             pw.println();
@@ -1668,6 +1709,22 @@
         }
     }
 
+    private void initializeDisplayPowerControllersLocked() {
+        mLogicalDisplayMapper.forEachLocked((logicalDisplay) -> addDisplayPowerControllerLocked(
+                logicalDisplay.getDisplayIdLocked()));
+    }
+
+    private void addDisplayPowerControllerLocked(int displayId) {
+        if (mPowerHandler == null) {
+            // initPowerManagement has not yet been called.
+            return;
+        }
+        final DisplayPowerController displayPowerController = new DisplayPowerController(
+                mContext, mDisplayPowerCallbacks, mPowerHandler, mSensorManager,
+                mDisplayBlanker, displayId);
+        mDisplayPowerControllers.append(displayId, displayPowerController);
+    }
+
     private final class DisplayManagerHandler extends Handler {
         public DisplayManagerHandler(Looper looper) {
             super(looper, null, true /*async*/);
@@ -2187,7 +2244,8 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
-                    return mDisplayPowerController.getBrightnessEvents(userId, hasUsageStats);
+                    return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+                            .getBrightnessEvents(userId, hasUsageStats);
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -2204,7 +2262,8 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
-                    return mDisplayPowerController.getAmbientBrightnessStats(userId);
+                    return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+                            .getAmbientBrightnessStats(userId);
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -2252,7 +2311,8 @@
                     BrightnessConfiguration config =
                             mPersistentDataStore.getBrightnessConfiguration(userSerial);
                     if (config == null) {
-                        config = mDisplayPowerController.getDefaultBrightnessConfiguration();
+                        config = mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+                                .getDefaultBrightnessConfiguration();
                     }
                     return config;
                 }
@@ -2269,7 +2329,8 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
-                    return mDisplayPowerController.getDefaultBrightnessConfiguration();
+                    return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+                            .getDefaultBrightnessConfiguration();
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -2292,7 +2353,8 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
-                    mDisplayPowerController.setTemporaryBrightness(brightness);
+                    mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+                            .setTemporaryBrightness(brightness);
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -2307,7 +2369,8 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
-                    mDisplayPowerController.setTemporaryAutoBrightnessAdjustment(adjustment);
+                    mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+                            .setTemporaryAutoBrightnessAdjustment(adjustment);
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -2428,25 +2491,10 @@
         public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
                 SensorManager sensorManager) {
             synchronized (mSyncRoot) {
-                DisplayBlanker blanker = new DisplayBlanker() {
-                    @Override
-                    public void requestDisplayState(int displayId, int state, float brightness) {
-                        // The order of operations is important for legacy reasons.
-                        if (state == Display.STATE_OFF) {
-                            requestGlobalDisplayStateInternal(state, brightness);
-                        }
-
-                        callbacks.onDisplayStateChange(state);
-
-                        if (state != Display.STATE_OFF) {
-                            requestGlobalDisplayStateInternal(state, brightness);
-                        }
-                    }
-                };
-                mDisplayPowerController = new DisplayPowerController(
-                        mContext, callbacks, handler, sensorManager, blanker,
-                        Display.DEFAULT_DISPLAY);
+                mDisplayPowerCallbacks = callbacks;
                 mSensorManager = sensorManager;
+                mPowerHandler = handler;
+                initializeDisplayPowerControllersLocked();
             }
 
             mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION);
@@ -2456,14 +2504,16 @@
         public boolean requestPowerState(DisplayPowerRequest request,
                 boolean waitForNegativeProximity) {
             synchronized (mSyncRoot) {
-                return mDisplayPowerController.requestPowerState(request, waitForNegativeProximity);
+                return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+                        .requestPowerState(request, waitForNegativeProximity);
             }
         }
 
         @Override
         public boolean isProximitySensorAvailable() {
             synchronized (mSyncRoot) {
-                return mDisplayPowerController.isProximitySensorAvailable();
+                return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+                        .isProximitySensorAvailable();
             }
         }
 
@@ -2552,7 +2602,8 @@
         @Override
         public void persistBrightnessTrackerState() {
             synchronized (mSyncRoot) {
-                mDisplayPowerController.persistBrightnessTrackerState();
+                mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+                        .persistBrightnessTrackerState();
             }
         }
 
@@ -2584,7 +2635,8 @@
 
         @Override
         public void ignoreProximitySensorUntilChanged() {
-            mDisplayPowerController.ignoreProximitySensorUntilChanged();
+            mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+                    .ignoreProximitySensorUntilChanged();
         }
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 0211876..309271c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1815,6 +1815,10 @@
     public void dump(final PrintWriter pw) {
         synchronized (mLock) {
             pw.println();
+            pw.println("Display Power Controller:");
+            pw.println("  mDisplayId=" + mDisplayId);
+
+            pw.println();
             pw.println("Display Power Controller Locked State:");
             pw.println("  mDisplayReadyLocked=" + mDisplayReadyLocked);
             pw.println("  mPendingRequestLocked=" + mPendingRequestLocked);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 16a4b72..b532fa1 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -234,7 +234,6 @@
     static final int MSG_SET_ACTIVE = 3020;
     static final int MSG_SET_INTERACTIVE = 3030;
     static final int MSG_REPORT_FULLSCREEN_MODE = 3045;
-    static final int MSG_REPORT_PRE_RENDERED = 3060;
     static final int MSG_APPLY_IME_VISIBILITY = 3070;
 
     static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
@@ -317,8 +316,6 @@
     private static final class DebugFlags {
         static final DebugFlag FLAG_OPTIMIZE_START_INPUT =
                 new DebugFlag("debug.optimize_startinput", false);
-        static final DebugFlag FLAG_PRE_RENDER_IME_VIEWS =
-                new DebugFlag("persist.pre_render_ime_views", false);
     }
 
     @UserIdInt
@@ -448,10 +445,6 @@
         final ClientDeathRecipient clientDeathRecipient;
 
         boolean sessionRequested;
-        // Determines if IMEs should be pre-rendered.
-        // DebugFlag can be flipped anytime. This flag is kept per-client to maintain behavior
-        // through the life of the current client.
-        boolean shouldPreRenderIme;
         SessionState curSession;
 
         @Override
@@ -3440,14 +3433,6 @@
             return InputBindResult.USER_SWITCHING;
         }
 
-        // Main feature flag that overrides other conditions and forces IME preRendering.
-        if (DEBUG) {
-            Slog.v(TAG, "IME PreRendering main flag: "
-                    + DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.value() + ", LowRam: " + mIsLowRam);
-        }
-        // pre-rendering not supported on low-ram devices.
-        cs.shouldPreRenderIme = DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.value() && !mIsLowRam;
-
         final boolean sameWindowFocused = mCurFocusedWindow == windowToken;
         final boolean isTextEditor = (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0;
         final boolean startInputByWinGainedFocus =
@@ -4141,19 +4126,6 @@
     }
 
     @BinderThread
-    private void reportPreRendered(IBinder token, EditorInfo info) {
-        synchronized (mMethodMap) {
-            if (!calledWithValidTokenLocked(token)) {
-                return;
-            }
-            if (mCurClient != null && mCurClient.client != null) {
-                executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
-                        MSG_REPORT_PRE_RENDERED, info, mCurClient));
-            }
-        }
-    }
-
-    @BinderThread
     private void applyImeVisibility(IBinder token, IBinder windowToken, boolean setVisible) {
         synchronized (mMethodMap) {
             if (!calledWithValidTokenLocked(token)) {
@@ -4430,7 +4402,7 @@
                 try {
                     setEnabledSessionInMainThread(session);
                     session.method.startInput(startInputToken, inputContext, missingMethods,
-                            editorInfo, restarting, session.client.shouldPreRenderIme);
+                            editorInfo, restarting);
                 } catch (RemoteException e) {
                 }
                 args.recycle();
@@ -4488,20 +4460,6 @@
                 }
                 return true;
             }
-            case MSG_REPORT_PRE_RENDERED: {
-                args = (SomeArgs) msg.obj;
-                final EditorInfo info = (EditorInfo) args.arg1;
-                final ClientState clientState = (ClientState) args.arg2;
-                try {
-                    clientState.client.reportPreRendered(info);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Got RemoteException sending "
-                            + "reportPreRendered(" + info + ") notification to pid="
-                            + clientState.pid + " uid=" + clientState.uid);
-                }
-                args.recycle();
-                return true;
-            }
             case MSG_APPLY_IME_VISIBILITY: {
                 final boolean setVisible = msg.arg1 != 0;
                 final ClientState clientState = (ClientState) msg.obj;
@@ -5347,7 +5305,6 @@
         @ShellCommandResult
         private int refreshDebugProperties() {
             DebugFlags.FLAG_OPTIMIZE_START_INPUT.refresh();
-            DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.refresh();
             return ShellCommandResult.SUCCESS;
         }
 
@@ -5822,12 +5779,6 @@
 
         @BinderThread
         @Override
-        public void reportPreRendered(EditorInfo info) {
-            mImms.reportPreRendered(mToken, info);
-        }
-
-        @BinderThread
-        @Override
         public void applyImeVisibility(IBinder windowToken, boolean setVisible) {
             mImms.applyImeVisibility(mToken, windowToken, setVisible);
         }
diff --git a/services/core/java/com/android/server/location/ContextHubServiceUtil.java b/services/core/java/com/android/server/location/ContextHubServiceUtil.java
index 76cd9ce..9145eca 100644
--- a/services/core/java/com/android/server/location/ContextHubServiceUtil.java
+++ b/services/core/java/com/android/server/location/ContextHubServiceUtil.java
@@ -30,12 +30,16 @@
 import android.hardware.location.NanoAppBinary;
 import android.hardware.location.NanoAppMessage;
 import android.hardware.location.NanoAppState;
+import android.os.Binder;
+import android.os.Build;
 import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * A class encapsulating helper functions used by the ContextHubService class
@@ -45,6 +49,9 @@
     private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
     private static final String CONTEXT_HUB_PERMISSION = Manifest.permission.ACCESS_CONTEXT_HUB;
 
+    // A set of packages that have already been warned regarding the ACCESS_CONTEXT_HUB permission.
+    private static final Set<String> PERMISSION_WARNED_PACKAGES = new HashSet<String>();
+
     /**
      * Creates a ConcurrentHashMap of the Context Hub ID to the ContextHubInfo object given an
      * ArrayList of HIDL ContextHub objects.
@@ -95,6 +102,7 @@
 
     /**
      * Creates a primitive integer array given a Collection<Integer>.
+     *
      * @param collection the collection to iterate
      * @return the primitive integer array
      */
@@ -200,10 +208,25 @@
      */
     /* package */
     static void checkPermissions(Context context) {
-        if (context.checkCallingPermission(HARDWARE_PERMISSION) != PERMISSION_GRANTED
-                && context.checkCallingPermission(CONTEXT_HUB_PERMISSION) != PERMISSION_GRANTED) {
+        boolean hasLocationHardwarePermission = (context.checkCallingPermission(HARDWARE_PERMISSION)
+                == PERMISSION_GRANTED);
+        boolean hasAccessContextHubPermission = (context.checkCallingPermission(
+                CONTEXT_HUB_PERMISSION) == PERMISSION_GRANTED);
+
+        if (!hasLocationHardwarePermission && !hasAccessContextHubPermission) {
             throw new SecurityException(
-                "LOCATION_HARDWARE or ACCESS_CONTEXT_HUB permission required to use Context Hub");
+                    "LOCATION_HARDWARE or ACCESS_CONTEXT_HUB permission required to use Context "
+                            + "Hub");
+        }
+
+        if (!hasAccessContextHubPermission && !Build.IS_USER) {
+            String pkgName = context.getPackageManager().getNameForUid(Binder.getCallingUid());
+            if (!PERMISSION_WARNED_PACKAGES.contains(pkgName)) {
+                Log.w(TAG, pkgName
+                        + ": please use the ACCESS_CONTEXT_HUB permission rather than "
+                        + "LOCATION_HARDWARE (will be removed for Context Hub APIs in T)");
+                PERMISSION_WARNED_PACKAGES.add(pkgName);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java
index f25c651..f8d1195 100644
--- a/services/core/java/com/android/server/location/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/LocationProviderManager.java
@@ -38,6 +38,7 @@
 import static java.lang.Math.max;
 import static java.lang.Math.min;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.AlarmManager.OnAlarmListener;
 import android.app.PendingIntent;
@@ -107,6 +108,8 @@
 import com.android.server.location.util.UserInfoHelper.UserListener;
 
 import java.io.FileDescriptor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -142,6 +145,14 @@
     // will just be scheduled immediately
     private static final long MIN_REQUEST_DELAY_MS = 30 * 1000;
 
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({STATE_STARTED, STATE_STOPPING, STATE_STOPPED})
+    private @interface State {}
+
+    private static final int STATE_STARTED = 0;
+    private static final int STATE_STOPPING = 1;
+    private static final int STATE_STOPPED = 2;
+
     protected interface LocationTransport {
 
         void deliverOnLocationChanged(Location location, @Nullable Runnable onCompleteCallback)
@@ -1082,7 +1093,7 @@
     protected final Context mContext;
 
     @GuardedBy("mLock")
-    private boolean mStarted;
+    private @State int mState;
 
     // maps of user id to value
     @GuardedBy("mLock")
@@ -1148,7 +1159,7 @@
         mContext = context;
         mName = Objects.requireNonNull(name);
         mPassiveManager = passiveManager;
-        mStarted = false;
+        mState = STATE_STOPPED;
         mEnabled = new SparseBooleanArray(2);
         mLastLocations = new SparseArray<>(2);
 
@@ -1180,7 +1191,8 @@
 
     public void startManager() {
         synchronized (mLock) {
-            mStarted = true;
+            Preconditions.checkState(mState == STATE_STOPPED);
+            mState = STATE_STARTED;
 
             mUserHelper.addListener(mUserChangedListener);
             mSettingsHelper.addOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
@@ -1197,6 +1209,9 @@
 
     public void stopManager() {
         synchronized (mLock) {
+            Preconditions.checkState(mState == STATE_STARTED);
+            mState = STATE_STOPPING;
+
             final long identity = Binder.clearCallingIdentity();
             try {
                 onEnabledChanged(UserHandle.USER_ALL);
@@ -1205,11 +1220,19 @@
                 Binder.restoreCallingIdentity(identity);
             }
 
+            setRealProvider(null);
+            setMockProvider(null);
+
             mUserHelper.removeListener(mUserChangedListener);
             mSettingsHelper.removeOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
 
+            // if external entities are registering listeners it's their responsibility to
+            // unregister them before stopManager() is called
             Preconditions.checkState(mEnabledListeners.isEmpty());
-            mStarted = false;
+
+            mEnabled.clear();
+            mLastLocations.clear();
+            mState = STATE_STOPPED;
         }
     }
 
@@ -1252,21 +1275,21 @@
 
     public void addEnabledListener(ProviderEnabledListener listener) {
         synchronized (mLock) {
-            Preconditions.checkState(mStarted);
+            Preconditions.checkState(mState != STATE_STOPPED);
             mEnabledListeners.add(listener);
         }
     }
 
     public void removeEnabledListener(ProviderEnabledListener listener) {
         synchronized (mLock) {
-            Preconditions.checkState(mStarted);
+            Preconditions.checkState(mState != STATE_STOPPED);
             mEnabledListeners.remove(listener);
         }
     }
 
-    public void setRealProvider(AbstractLocationProvider provider) {
+    public void setRealProvider(@Nullable AbstractLocationProvider provider) {
         synchronized (mLock) {
-            Preconditions.checkState(mStarted);
+            Preconditions.checkState(mState != STATE_STOPPED);
 
             final long identity = Binder.clearCallingIdentity();
             try {
@@ -1279,7 +1302,7 @@
 
     public void setMockProvider(@Nullable MockProvider provider) {
         synchronized (mLock) {
-            Preconditions.checkState(mStarted);
+            Preconditions.checkState(mState != STATE_STOPPED);
 
             mLocationEventLog.logProviderMocked(mName, provider != null);
 
@@ -1408,7 +1431,7 @@
 
         Location location;
         synchronized (mLock) {
-            Preconditions.checkState(mStarted);
+            Preconditions.checkState(mState != STATE_STOPPED);
             LastLocation lastLocation = mLastLocations.get(userId);
             if (lastLocation == null) {
                 location = null;
@@ -1430,7 +1453,7 @@
 
     public void injectLastLocation(Location location, int userId) {
         synchronized (mLock) {
-            Preconditions.checkState(mStarted);
+            Preconditions.checkState(mState != STATE_STOPPED);
             if (getLastLocationUnsafe(userId, PERMISSION_FINE, false, Long.MAX_VALUE) == null) {
                 setLastLocation(location, userId);
             }
@@ -1478,7 +1501,7 @@
                         permissionLevel);
 
         synchronized (mLock) {
-            Preconditions.checkState(mStarted);
+            Preconditions.checkState(mState != STATE_STOPPED);
             final long ident = Binder.clearCallingIdentity();
             try {
                 putRegistration(callback.asBinder(), registration);
@@ -1520,7 +1543,7 @@
                 permissionLevel);
 
         synchronized (mLock) {
-            Preconditions.checkState(mStarted);
+            Preconditions.checkState(mState != STATE_STOPPED);
             final long ident = Binder.clearCallingIdentity();
             try {
                 putRegistration(listener.asBinder(), registration);
@@ -1539,7 +1562,7 @@
                 permissionLevel);
 
         synchronized (mLock) {
-            Preconditions.checkState(mStarted);
+            Preconditions.checkState(mState != STATE_STOPPED);
             final long identity = Binder.clearCallingIdentity();
             try {
                 putRegistration(pendingIntent, registration);
@@ -1551,7 +1574,7 @@
 
     public void unregisterLocationRequest(ILocationListener listener) {
         synchronized (mLock) {
-            Preconditions.checkState(mStarted);
+            Preconditions.checkState(mState != STATE_STOPPED);
             final long identity = Binder.clearCallingIdentity();
             try {
                 removeRegistration(listener.asBinder());
@@ -1563,7 +1586,7 @@
 
     public void unregisterLocationRequest(PendingIntent pendingIntent) {
         synchronized (mLock) {
-            Preconditions.checkState(mStarted);
+            Preconditions.checkState(mState != STATE_STOPPED);
             final long identity = Binder.clearCallingIdentity();
             try {
                 removeRegistration(pendingIntent);
@@ -1890,6 +1913,10 @@
 
     private void onUserChanged(int userId, int change) {
         synchronized (mLock) {
+            if (mState == STATE_STOPPED) {
+                return;
+            }
+
             switch (change) {
                 case UserListener.CURRENT_USER_CHANGED:
                     updateRegistrations(
@@ -1907,6 +1934,10 @@
 
     private void onLocationEnabledChanged(int userId) {
         synchronized (mLock) {
+            if (mState == STATE_STOPPED) {
+                return;
+            }
+
             onEnabledChanged(userId);
         }
     }
@@ -2105,7 +2136,7 @@
 
         Preconditions.checkArgument(userId >= 0);
 
-        boolean enabled = mStarted
+        boolean enabled = mState == STATE_STARTED
                 && mProvider.getState().allowed
                 && mSettingsHelper.isLocationEnabled(userId);
 
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index e25e605..0c1e91d 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -583,8 +583,10 @@
         mDownloadPsdsWakeLock.setReferenceCounted(true);
 
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
-        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
+        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP),
+                PendingIntent.FLAG_IMMUTABLE);
+        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT),
+                PendingIntent.FLAG_IMMUTABLE);
 
         // App ops service to keep track of who is accessing the GPS
         mAppOps = mContext.getSystemService(AppOpsManager.class);
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index b679c0f..dd33865 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -1563,7 +1563,7 @@
                             continue;
                         }
                         try {
-                            listener.onPackageProgressChanged(mUser, mPackageName, progress);
+                            listener.onPackageLoadingProgressChanged(mUser, mPackageName, progress);
                         } catch (RemoteException re) {
                             Slog.d(TAG, "Callback failed ", re);
                         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index cdd347b..b3f49ad 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2737,7 +2737,7 @@
                 context, lock, installer, installLock, new PackageAbiHelperImpl(),
                 backgroundHandler,
                 (i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
-                (i, pm) -> PermissionManagerService.create(context, lock),
+                (i, pm) -> PermissionManagerService.create(context),
                 (i, pm) -> new UserManagerService(context, pm,
                         new UserDataPreparer(installer, installLock, context, onlyCore),
                         lock),
@@ -19606,7 +19606,7 @@
                         ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
                     }
 
-                    mSettings.writeRuntimePermissionsForUserLPr(userId, false);
+                    writeRuntimePermissionsForUserLPrTEMP(userId, false);
                 }
                 // Regardless of writeSettings we need to ensure that this restriction
                 // state propagation is persisted
@@ -25752,7 +25752,7 @@
         public void writePermissionSettings(int[] userIds, boolean async) {
             synchronized (mLock) {
                 for (int userId : userIds) {
-                    mSettings.writeRuntimePermissionsForUserLPr(userId, !async);
+                    writeRuntimePermissionsForUserLPrTEMP(userId, !async);
                 }
             }
         }
@@ -26401,6 +26401,17 @@
         mSettings.writeLPr();
     }
 
+    /**
+     * Temporary method that wraps mSettings.writeRuntimePermissionsForUserLPr() and calls
+     * mPermissionManager.writeLegacyPermissionStateTEMP() beforehand.
+     *
+     * TODO(zhanghai): This should be removed once we finish migration of permission storage.
+     */
+    private void writeRuntimePermissionsForUserLPrTEMP(@UserIdInt int userId, boolean async) {
+        mPermissionManager.writeLegacyPermissionStateTEMP();
+        mSettings.writeRuntimePermissionsForUserLPr(userId, async);
+    }
+
     @Override
     public IBinder getHoldLockToken() {
         if (!Build.IS_DEBUGGABLE) {
diff --git a/services/core/java/com/android/server/pm/permission/Permission.java b/services/core/java/com/android/server/pm/permission/Permission.java
index c121e6b..4e8ddac 100644
--- a/services/core/java/com/android/server/pm/permission/Permission.java
+++ b/services/core/java/com/android/server/pm/permission/Permission.java
@@ -378,28 +378,33 @@
         }
     }
 
+    public static boolean isOverridingSystemPermission(@Nullable Permission permission,
+            @NonNull PermissionInfo permissionInfo,
+            @NonNull PackageManagerInternal packageManagerInternal) {
+        if (permission == null || Objects.equals(permission.mPermissionInfo.packageName,
+                permissionInfo.packageName)) {
+            return false;
+        }
+        if (!permission.mReconciled) {
+            return false;
+        }
+        final AndroidPackage currentPackage = packageManagerInternal.getPackage(
+                permission.mPermissionInfo.packageName);
+        if (currentPackage == null) {
+            return false;
+        }
+        return currentPackage.isSystem();
+    }
+
     @NonNull
-    static Permission createOrUpdate(PackageManagerInternal packageManagerInternal,
-            @Nullable Permission permission, @NonNull PermissionInfo permissionInfo,
-            @NonNull AndroidPackage pkg, @NonNull Collection<Permission> permissionTrees,
+    public static Permission createOrUpdate(@Nullable Permission permission,
+            @NonNull PermissionInfo permissionInfo, @NonNull AndroidPackage pkg,
+            @NonNull Collection<Permission> permissionTrees, boolean isOverridingSystemPermission,
             boolean chatty) {
         // Allow system apps to redefine non-system permissions
         boolean ownerChanged = false;
         if (permission != null && !Objects.equals(permission.mPermissionInfo.packageName,
                 permissionInfo.packageName)) {
-            final boolean currentOwnerIsSystem;
-            if (!permission.mReconciled) {
-                currentOwnerIsSystem = false;
-            } else {
-                AndroidPackage currentPackage = packageManagerInternal.getPackage(
-                        permission.mPermissionInfo.packageName);
-                if (currentPackage == null) {
-                    currentOwnerIsSystem = false;
-                } else {
-                    currentOwnerIsSystem = currentPackage.isSystem();
-                }
-            }
-
             if (pkg.isSystem()) {
                 if (permission.mType == Permission.TYPE_CONFIG && !permission.mReconciled) {
                     // It's a built-in permission and no owner, take ownership now
@@ -407,11 +412,10 @@
                     permission.mPermissionInfo = permissionInfo;
                     permission.mReconciled = true;
                     permission.mUid = pkg.getUid();
-                } else if (!currentOwnerIsSystem) {
-                    String msg = "New decl " + pkg + " of permission  "
+                } else if (!isOverridingSystemPermission) {
+                    Slog.w(TAG, "New decl " + pkg + " of permission  "
                             + permissionInfo.name + " is system; overriding "
-                            + permission.mPermissionInfo.packageName;
-                    PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+                            + permission.mPermissionInfo.packageName);
                     ownerChanged = true;
                     permission = null;
                 }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 6d987ae..84f9823 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -208,7 +208,7 @@
     }
 
     /** Lock to protect internal data access */
-    private final Object mLock;
+    private final Object mLock = new Object();
 
     /** Internal connection to the package manager */
     private final PackageManagerInternal mPackageManagerInt;
@@ -224,6 +224,8 @@
     private PermissionControllerManager mPermissionControllerManager;
 
     /** Map of OneTimePermissionUserManagers keyed by userId */
+    @GuardedBy("mLock")
+    @NonNull
     private final SparseArray<OneTimePermissionUserManager> mOneTimePermissionUserManagers =
             new SparseArray<>();
 
@@ -252,12 +254,14 @@
 
     /** Internal storage for permissions and related settings */
     @GuardedBy("mLock")
-    private final PermissionRegistry mRegistry;
+    @NonNull
+    private final PermissionRegistry mRegistry = new PermissionRegistry();
 
     /** Injector that can be used to facilitate testing. */
     private final Injector mInjector;
 
     @GuardedBy("mLock")
+    @Nullable
     private ArraySet<String> mPrivappPermissionsViolations;
 
     @GuardedBy("mLock")
@@ -267,13 +271,6 @@
     private PermissionPolicyInternal mPermissionPolicyInternal;
 
     /**
-     * For each foreground/background permission the mapping:
-     * Background permission -> foreground permissions
-     */
-    @GuardedBy("mLock")
-    private ArrayMap<String, List<String>> mBackgroundPermissions;
-
-    /**
      * A permission backup might contain apps that are not installed. In this case we delay the
      * restoration until the app is installed.
      *
@@ -291,7 +288,7 @@
     @GuardedBy("mLock")
     private CheckPermissionDelegate mCheckPermissionDelegate;
 
-    @GuardedBy("mLock")
+    @NonNull
     private final OnPermissionChangeListeners mOnPermissionChangeListeners;
 
     @GuardedBy("mLock")
@@ -309,7 +306,7 @@
     // purposes. It may make sense to keep as an abstraction, but, the methods
     // necessary to be overridden may be different than what was initially needed
     // for the split.
-    private PermissionCallback mDefaultPermissionCallback = new PermissionCallback() {
+    private final PermissionCallback mDefaultPermissionCallback = new PermissionCallback() {
         @Override
         public void onGidsChanged(int appId, int userId) {
             mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED));
@@ -368,14 +365,12 @@
         }
     };
 
-    PermissionManagerService(Context context,
-            @NonNull Object externalLock) {
-        this(context, externalLock, new Injector(context));
+    PermissionManagerService(@NonNull Context context) {
+        this(context, new Injector(context));
     }
 
     @VisibleForTesting
-    PermissionManagerService(Context context, @NonNull Object externalLock,
-            @NonNull Injector injector) {
+    PermissionManagerService(@NonNull Context context, @NonNull Injector injector) {
         mInjector = injector;
         // The package info cache is the cache for package and permission information.
         // Disable the package info and package permission caches locally but leave the
@@ -384,10 +379,8 @@
         mInjector.disablePackageNamePermissionCache();
 
         mContext = context;
-        mLock = externalLock;
         mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
         mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
-        mRegistry = new PermissionRegistry(mLock);
         mAppOpsManager = context.getSystemService(AppOpsManager.class);
 
         mHandlerThread = new ServiceThread(TAG,
@@ -409,10 +402,10 @@
         synchronized (mLock) {
             for (int i=0; i<permConfig.size(); i++) {
                 final SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
-                Permission bp = mRegistry.getPermissionLocked(perm.name);
+                Permission bp = mRegistry.getPermission(perm.name);
                 if (bp == null) {
                     bp = new Permission(perm.name, "android", Permission.TYPE_CONFIG);
-                    mRegistry.addPermissionLocked(bp);
+                    mRegistry.addPermission(bp);
                 }
                 if (perm.gids != null) {
                     bp.setGids(perm.gids, perm.perUser);
@@ -444,8 +437,8 @@
      * NOTE: The external lock is temporary and should be removed. This needs to be a
      * lock created by the permission manager itself.
      */
-    public static PermissionManagerServiceInternal create(Context context,
-            @NonNull Object externalLock) {
+    @NonNull
+    public static PermissionManagerServiceInternal create(@NonNull Context context) {
         final PermissionManagerServiceInternal permMgrInt =
                 LocalServices.getService(PermissionManagerServiceInternal.class);
         if (permMgrInt != null) {
@@ -454,8 +447,7 @@
         PermissionManagerService permissionService =
                 (PermissionManagerService) ServiceManager.getService("permissionmgr");
         if (permissionService == null) {
-            permissionService =
-                    new PermissionManagerService(context, externalLock);
+            permissionService = new PermissionManagerService(context);
             ServiceManager.addService("permissionmgr", permissionService);
         }
         return LocalServices.getService(PermissionManagerServiceInternal.class);
@@ -484,13 +476,6 @@
         }
     }
 
-    @Nullable
-    Permission getPermission(String permName) {
-        synchronized (mLock) {
-            return mRegistry.getPermissionLocked(permName);
-        }
-    }
-
     @Override
     public String[] getAppOpPermissionPackages(String permName) {
         return getAppOpPermissionPackagesInternal(permName, getCallingUid());
@@ -501,7 +486,7 @@
             return null;
         }
         synchronized (mLock) {
-            final ArraySet<String> pkgs = mRegistry.getAppOpPermissionPackagesLocked(permName);
+            final ArraySet<String> pkgs = mRegistry.getAppOpPermissionPackages(permName);
             if (pkgs == null) {
                 return null;
             }
@@ -519,7 +504,7 @@
         }
         synchronized (mLock) {
             final List<PermissionGroupInfo> out = new ArrayList<>();
-            for (ParsedPermissionGroup pg : mRegistry.getPermissionGroupsLocked()) {
+            for (ParsedPermissionGroup pg : mRegistry.getPermissionGroups()) {
                 out.add(PackageInfoUtils.generatePermissionGroupInfo(pg, flags));
             }
             return new ParceledListSlice<>(out);
@@ -537,7 +522,7 @@
         }
         synchronized (mLock) {
             return PackageInfoUtils.generatePermissionGroupInfo(
-                    mRegistry.getPermissionGroupLocked(groupName), flags);
+                    mRegistry.getPermissionGroup(groupName), flags);
         }
     }
 
@@ -554,7 +539,7 @@
         final int targetSdkVersion = getPermissionInfoCallingTargetSdkVersion(opPackage,
                 callingUid);
         synchronized (mLock) {
-            final Permission bp = mRegistry.getPermissionLocked(permName);
+            final Permission bp = mRegistry.getPermission(permName);
             if (bp == null) {
                 return null;
             }
@@ -584,11 +569,11 @@
             return null;
         }
         synchronized (mLock) {
-            if (groupName != null && mRegistry.getPermissionGroupLocked(groupName) == null) {
+            if (groupName != null && mRegistry.getPermissionGroup(groupName) == null) {
                 return null;
             }
             final ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
-            for (Permission bp : mRegistry.getPermissionsLocked()) {
+            for (Permission bp : mRegistry.getPermissions()) {
                 if (Objects.equals(bp.getGroup(), groupName)) {
                     out.add(bp.generatePermissionInfo(flags));
                 }
@@ -606,24 +591,23 @@
         if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
             throw new SecurityException("Label must be specified in permission");
         }
-        final Permission tree = mRegistry.enforcePermissionTree(info.name, callingUid);
         final boolean added;
         final boolean changed;
         synchronized (mLock) {
-            Permission bp = mRegistry.getPermissionLocked(info.name);
+            final Permission tree = mRegistry.enforcePermissionTree(info.name, callingUid);
+            Permission bp = mRegistry.getPermission(info.name);
             added = bp == null;
             int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
             if (added) {
                 enforcePermissionCapLocked(info, tree);
-                bp = new Permission(info.name, tree.getPackageName(),
-                        Permission.TYPE_DYNAMIC);
+                bp = new Permission(info.name, tree.getPackageName(), Permission.TYPE_DYNAMIC);
             } else if (!bp.isDynamic()) {
                 throw new SecurityException("Not allowed to modify non-dynamic permission "
                         + info.name);
             }
             changed = bp.addToTree(fixedLevel, info, tree);
             if (added) {
-                mRegistry.addPermissionLocked(bp);
+                mRegistry.addPermission(bp);
             }
         }
         if (changed) {
@@ -638,9 +622,9 @@
         if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
             throw new SecurityException("Instant applications don't have access to this method");
         }
-        final Permission tree = mRegistry.enforcePermissionTree(permName, callingUid);
         synchronized (mLock) {
-            final Permission bp = mRegistry.getPermissionLocked(permName);
+            mRegistry.enforcePermissionTree(permName, callingUid);
+            final Permission bp = mRegistry.getPermission(permName);
             if (bp == null) {
                 return;
             }
@@ -649,9 +633,9 @@
                 Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
                         + permName);
             }
-            mRegistry.removePermissionLocked(permName);
-            mPackageManagerInt.writeSettings(false);
+            mRegistry.removePermission(permName);
         }
+        mPackageManagerInt.writeSettings(false);
     }
 
     @Override
@@ -682,7 +666,7 @@
         }
 
         synchronized (mLock) {
-            if (mRegistry.getPermissionLocked(permName) == null) {
+            if (mRegistry.getPermission(permName) == null) {
                 return 0;
             }
 
@@ -807,14 +791,16 @@
             }
         }
 
-        final Permission bp;
+        final boolean isRuntimePermission;
         final boolean permissionUpdated;
         synchronized (mLock) {
-            bp = mRegistry.getPermissionLocked(permName);
+            final Permission bp = mRegistry.getPermission(permName);
             if (bp == null) {
                 throw new IllegalArgumentException("Unknown permission: " + permName);
             }
 
+            isRuntimePermission = bp.isRuntime();
+
             if (bp.isInstallerExemptIgnored()) {
                 flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
             }
@@ -833,14 +819,14 @@
             permissionUpdated = uidState.updatePermissionFlags(bp, flagMask, flagValues);
         }
 
-        if (permissionUpdated && bp.isRuntime()) {
+        if (permissionUpdated && isRuntimePermission) {
             notifyRuntimePermissionStateChanged(packageName, userId);
         }
         if (permissionUpdated && callback != null) {
             // Install and runtime permissions are stored in different places,
             // so figure out what permission changed and persist the change.
-            if (!bp.isRuntime()) {
-                int userUid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid()));
+            if (!isRuntimePermission) {
+                int userUid = UserHandle.getUid(userId, pkg.getUid());
                 callback.onInstallPermissionUpdatedNotifyListener(userUid);
             } else {
                 callback.onPermissionUpdatedNotifyListener(new int[]{userId}, false, pkg.getUid());
@@ -962,6 +948,7 @@
         return PackageManager.PERMISSION_DENIED;
     }
 
+    @GuardedBy("mLock")
     private boolean checkSinglePermissionInternalLocked(@NonNull UidPermissionState uidState,
             @NonNull String permissionName, boolean isInstantApp) {
         if (!uidState.isPermissionGranted(permissionName)) {
@@ -969,7 +956,8 @@
         }
 
         if (isInstantApp) {
-            return mRegistry.isPermissionInstant(permissionName);
+            final Permission permission = mRegistry.getPermission(permissionName);
+            return permission != null && permission.isInstant();
         }
 
         return true;
@@ -1031,6 +1019,7 @@
         return PackageManager.PERMISSION_DENIED;
     }
 
+    @GuardedBy("mLock")
     private boolean checkSingleUidPermissionInternalLocked(int uid,
             @NonNull String permissionName) {
         ArraySet<String> permissions = mSystemPermissions.get(uid);
@@ -1096,9 +1085,7 @@
                 Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS,
                 "addOnPermissionsChangeListener");
 
-        synchronized (mLock) {
-            mOnPermissionChangeListeners.addListenerLocked(listener);
-        }
+        mOnPermissionChangeListeners.addListener(listener);
     }
 
     @Override
@@ -1106,9 +1093,7 @@
         if (mPackageManagerInt.getInstantAppPackageName(Binder.getCallingUid()) != null) {
             throw new SecurityException("Instant applications don't have access to this method");
         }
-        synchronized (mLock) {
-            mOnPermissionChangeListeners.removeListenerLocked(listener);
-        }
+        mOnPermissionChangeListeners.removeListener(listener);
     }
 
     @Override
@@ -1230,21 +1215,23 @@
 
     private boolean checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(
             @NonNull String permName) {
+        final boolean isImmutablyRestrictedPermission;
         synchronized (mLock) {
-            final Permission bp = mRegistry.getPermissionLocked(permName);
+            final Permission bp = mRegistry.getPermission(permName);
             if (bp == null) {
                 Slog.w(TAG, "No such permissions: " + permName);
                 return false;
             }
-            if (bp.isHardOrSoftRestricted() && bp.isImmutablyRestricted()
-                    && mContext.checkCallingOrSelfPermission(
-                    Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Cannot modify whitelisting of an immutably "
-                        + "restricted permission: " + permName);
-            }
-            return true;
+            isImmutablyRestrictedPermission = bp.isHardOrSoftRestricted()
+                    && bp.isImmutablyRestricted();
         }
+        if (isImmutablyRestrictedPermission && mContext.checkCallingOrSelfPermission(
+                Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot modify whitelisting of an immutably "
+                    + "restricted permission: " + permName);
+        }
+        return true;
     }
 
     @Override
@@ -1472,36 +1459,33 @@
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
 
-        final Permission bp;
+        final boolean isSoftRestrictedPermission;
         synchronized (mLock) {
-            bp = mRegistry.getPermissionLocked(permName);
+            final Permission permission = mRegistry.getPermission(permName);
+            isSoftRestrictedPermission = permission != null && permission.isSoftRestricted();
         }
-        if (bp == null) {
-            throw new IllegalArgumentException("Unknown permission: " + permName);
-        }
+        final boolean mayGrantSoftRestrictedPermission = isSoftRestrictedPermission
+                && SoftRestrictedPermissionPolicy.forPermission(mContext,
+                        pkg.toAppInfoWithoutState(), pkg, UserHandle.of(userId), permName)
+                        .mayGrantPermission();
 
-        if (!(bp.isRuntime() || bp.isDevelopment())) {
-            throw new SecurityException("Permission " + permName + " requested by "
-                    + pkg.getPackageName() + " is not a changeable permission type");
-        }
-
-        // If a permission review is required for legacy apps we represent
-        // their permissions as always granted runtime ones since we need
-        // to keep the review required permission flag per user while an
-        // install permission's state is shared across all users.
-        if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) {
-            return;
-        }
-
-        if (bp.isSoftRestricted() && !SoftRestrictedPermissionPolicy.forPermission(mContext,
-                pkg.toAppInfoWithoutState(), pkg, UserHandle.of(userId), permName)
-                .mayGrantPermission()) {
-            Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
-                    + packageName);
-            return;
-        }
-
+        final boolean isRuntimePermission;
+        final boolean isDevelopmentPermission;
+        final boolean permissionHasGids;
         synchronized (mLock) {
+            final Permission bp = mRegistry.getPermission(permName);
+            if (bp == null) {
+                throw new IllegalArgumentException("Unknown permission: " + permName);
+            }
+
+            isRuntimePermission = bp.isRuntime();
+            isDevelopmentPermission = bp.isDevelopment();
+            permissionHasGids = bp.hasGids();
+            if (!(isRuntimePermission || isDevelopmentPermission)) {
+                throw new SecurityException("Permission " + permName + " requested by "
+                        + pkg.getPackageName() + " is not a changeable permission type");
+            }
+
             final UidPermissionState uidState = getUidStateLocked(pkg, userId);
             if (uidState == null) {
                 Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
@@ -1515,6 +1499,14 @@
                         + " has not requested permission " + permName);
             }
 
+            // If a permission review is required for legacy apps we represent
+            // their permissions as always granted runtime ones since we need
+            // to keep the review required permission flag per user while an
+            // install permission's state is shared across all users.
+            if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) {
+                return;
+            }
+
             final int flags = uidState.getPermissionFlags(permName);
             if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
                 Log.e(TAG, "Cannot grant system fixed permission "
@@ -1534,6 +1526,12 @@
                 return;
             }
 
+            if (bp.isSoftRestricted() && !mayGrantSoftRestrictedPermission) {
+                Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
+                        + packageName);
+                return;
+            }
+
             if (bp.isDevelopment()) {
                 // Development permissions must be handled specially, since they are not
                 // normal runtime permissions.  For now they apply to all users.
@@ -1559,23 +1557,23 @@
             }
         }
 
-        if (bp.isRuntime()) {
+        if (isRuntimePermission) {
             logPermission(MetricsEvent.ACTION_PERMISSION_GRANTED, permName, packageName);
         }
 
-        final int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid()));
+        final int uid = UserHandle.getUid(userId, pkg.getUid());
         if (callback != null) {
-            if (bp.isDevelopment()) {
+            if (isDevelopmentPermission) {
                 callback.onInstallPermissionGranted();
             } else {
                 callback.onPermissionGranted(uid, userId);
             }
-            if (bp.hasGids()) {
+            if (permissionHasGids) {
                 callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
             }
         }
 
-        if (bp.isRuntime()) {
+        if (isRuntimePermission) {
             notifyRuntimePermissionStateChanged(packageName, userId);
         }
     }
@@ -1626,17 +1624,22 @@
         if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
-        final Permission bp = mRegistry.getPermission(permName);
-        if (bp == null) {
-            throw new IllegalArgumentException("Unknown permission: " + permName);
-        }
 
-        if (!(bp.isRuntime() || bp.isDevelopment())) {
-            throw new SecurityException("Permission " + permName + " requested by "
-                    + pkg.getPackageName() + " is not a changeable permission type");
-        }
-
+        final boolean isRuntimePermission;
+        final boolean isDevelopmentPermission;
         synchronized (mLock) {
+            final Permission bp = mRegistry.getPermission(permName);
+            if (bp == null) {
+                throw new IllegalArgumentException("Unknown permission: " + permName);
+            }
+
+            isRuntimePermission = bp.isRuntime();
+            isDevelopmentPermission = bp.isDevelopment();
+            if (!(isRuntimePermission || isDevelopmentPermission)) {
+                throw new SecurityException("Permission " + permName + " requested by "
+                        + pkg.getPackageName() + " is not a changeable permission type");
+            }
+
             final UidPermissionState uidState = getUidStateLocked(pkg, userId);
             if (uidState == null) {
                 Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
@@ -1679,20 +1682,20 @@
             }
         }
 
-        if (bp.isRuntime()) {
+        if (isRuntimePermission) {
             logPermission(MetricsEvent.ACTION_PERMISSION_REVOKED, permName, packageName);
         }
 
         if (callback != null) {
-            if (bp.isDevelopment()) {
+            if (isDevelopmentPermission) {
                 mDefaultPermissionCallback.onInstallPermissionRevoked();
             } else {
-                callback.onPermissionRevoked(UserHandle.getUid(userId,
-                        UserHandle.getAppId(pkg.getUid())), userId, reason);
+                callback.onPermissionRevoked(UserHandle.getUid(userId, pkg.getUid()), userId,
+                        reason);
             }
         }
 
-        if (bp.isRuntime()) {
+        if (isRuntimePermission) {
             notifyRuntimePermissionStateChanged(packageName, userId);
         }
     }
@@ -1807,16 +1810,18 @@
 
         for (int i = 0; i < permissionCount; i++) {
             final String permName = pkg.getRequestedPermissions().get(i);
-            final Permission bp;
-            synchronized (mLock) {
-                bp = mRegistry.getPermissionLocked(permName);
-            }
-            if (bp == null) {
-                continue;
-            }
 
-            if (bp.isRemoved()) {
-                continue;
+            final boolean isRuntimePermission;
+            synchronized (mLock) {
+                final Permission permission = mRegistry.getPermission(permName);
+                if (permission == null) {
+                    continue;
+                }
+
+                if (permission.isRemoved()) {
+                    continue;
+                }
+                isRuntimePermission = permission.isRuntime();
             }
 
             // If shared user we just reset the state to which only this app contributed.
@@ -1846,7 +1851,7 @@
             // permission as requiring a review as this is the initial state.
             final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
             final int targetSdk = mPackageManagerInt.getUidTargetSdkVersion(uid);
-            final int flags = (targetSdk < Build.VERSION_CODES.M && bp.isRuntime())
+            final int flags = (targetSdk < Build.VERSION_CODES.M && isRuntimePermission)
                     ? FLAG_PERMISSION_REVIEW_REQUIRED | FLAG_PERMISSION_REVOKED_COMPAT
                     : 0;
 
@@ -1855,7 +1860,7 @@
                     false, delayingPermCallback);
 
             // Below is only runtime permission handling.
-            if (!bp.isRuntime()) {
+            if (!isRuntimePermission) {
                 continue;
             }
 
@@ -2092,13 +2097,15 @@
             return false;
         }
 
-        Permission permission = getPermission(permName);
-        if (permission == null) {
-            return false;
-        }
-        if (permission.isHardRestricted()
-                && (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
-            return false;
+        synchronized (mLock) {
+            final Permission permission = mRegistry.getPermission(permName);
+            if (permission == null) {
+                return false;
+            }
+            if (permission.isHardRestricted()
+                    && (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
+                return false;
+            }
         }
 
         final long token = Binder.clearCallingIdentity();
@@ -2177,8 +2184,8 @@
     private void restoreRuntimePermissions(@NonNull byte[] backup, @NonNull UserHandle user) {
         synchronized (mLock) {
             mHasNoDelayedPermBackup.delete(user.getIdentifier());
-            mPermissionControllerManager.stageAndApplyRuntimePermissionsBackup(backup, user);
         }
+        mPermissionControllerManager.stageAndApplyRuntimePermissionsBackup(backup, user);
     }
 
     /**
@@ -2197,18 +2204,16 @@
             if (mHasNoDelayedPermBackup.get(user.getIdentifier(), false)) {
                 return;
             }
-
-            mPermissionControllerManager.applyStagedRuntimePermissionBackup(packageName, user,
-                    mContext.getMainExecutor(), (hasMoreBackup) -> {
-                        if (hasMoreBackup) {
-                            return;
-                        }
-
-                        synchronized (mLock) {
-                            mHasNoDelayedPermBackup.put(user.getIdentifier(), true);
-                        }
-                    });
         }
+        mPermissionControllerManager.applyStagedRuntimePermissionBackup(packageName, user,
+                mContext.getMainExecutor(), (hasMoreBackup) -> {
+                    if (hasMoreBackup) {
+                        return;
+                    }
+                    synchronized (mLock) {
+                        mHasNoDelayedPermBackup.put(user.getIdentifier(), true);
+                    }
+                });
     }
 
     private void addOnRuntimePermissionStateChangedListener(@NonNull
@@ -2346,10 +2351,12 @@
         final int callingUid = Binder.getCallingUid();
 
         for (int permNum = 0; permNum < numPermissions; permNum++) {
-            String permName = permissionsToRevoke.get(permNum);
-            Permission bp = mRegistry.getPermission(permName);
-            if (bp == null || !bp.isRuntime()) {
-                continue;
+            final String permName = permissionsToRevoke.get(permNum);
+            synchronized (mLock) {
+                final Permission bp = mRegistry.getPermission(permName);
+                if (bp == null || !bp.isRuntime()) {
+                    continue;
+                }
             }
             for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
                 final int userId = userIds[userIdNum];
@@ -2387,7 +2394,6 @@
                     }
                 }
             }
-            bp.setDefinitionChanged(false);
         }
     }
 
@@ -2400,13 +2406,15 @@
             // Assume by default that we did not install this permission into the system.
             p.setFlags(p.getFlags() & ~PermissionInfo.FLAG_INSTALLED);
 
+            final PermissionInfo permissionInfo;
+            final Permission oldPermission;
             synchronized (mLock) {
                 // Now that permission groups have a special meaning, we ignore permission
                 // groups for legacy apps to prevent unexpected behavior. In particular,
                 // permissions for one app being granted to someone just because they happen
                 // to be in a group defined by another app (before this had no implications).
                 if (pkg.getTargetSdkVersion() > Build.VERSION_CODES.LOLLIPOP_MR1) {
-                    p.setParsedPermissionGroup(mRegistry.getPermissionGroupLocked(p.getGroup()));
+                    p.setParsedPermissionGroup(mRegistry.getPermissionGroup(p.getGroup()));
                     // Warn for a permission in an unknown group.
                     if (DEBUG_PERMISSIONS
                             && p.getGroup() != null && p.getParsedPermissionGroup() == null) {
@@ -2415,27 +2423,30 @@
                     }
                 }
 
-                final PermissionInfo permissionInfo = PackageInfoUtils.generatePermissionInfo(p,
+                permissionInfo = PackageInfoUtils.generatePermissionInfo(p,
                         PackageManager.GET_META_DATA);
-                final Permission bp;
+                oldPermission = p.isTree() ? mRegistry.getPermissionTree(p.getName())
+                        : mRegistry.getPermission(p.getName());
+            }
+            // TODO(zhanghai): Maybe we should store whether a permission is owned by system inside
+            //  itself.
+            final boolean isOverridingSystemPermission = Permission.isOverridingSystemPermission(
+                    oldPermission, permissionInfo, mPackageManagerInt);
+            synchronized (mLock) {
+                final Permission permission = Permission.createOrUpdate(oldPermission,
+                        permissionInfo, pkg, mRegistry.getPermissionTrees(),
+                        isOverridingSystemPermission, chatty);
                 if (p.isTree()) {
-                    bp = Permission.createOrUpdate(
-                            mPackageManagerInt,
-                            mRegistry.getPermissionTreeLocked(p.getName()), permissionInfo, pkg,
-                            mRegistry.getPermissionTreesLocked(), chatty);
-                    mRegistry.addPermissionTreeLocked(bp);
+                    mRegistry.addPermissionTree(permission);
                 } else {
-                    bp = Permission.createOrUpdate(
-                            mPackageManagerInt,
-                            mRegistry.getPermissionLocked(p.getName()),
-                            permissionInfo, pkg, mRegistry.getPermissionTreesLocked(), chatty);
-                    mRegistry.addPermissionLocked(bp);
+                    mRegistry.addPermission(permission);
                 }
-                if (bp.isInstalled()) {
+                if (permission.isInstalled()) {
                     p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED);
                 }
-                if (bp.isDefinitionChanged()) {
+                if (permission.isDefinitionChanged()) {
                     definitionChangedPermissions.add(p.getName());
+                    permission.setDefinitionChanged(false);
                 }
             }
         }
@@ -2448,11 +2459,11 @@
             StringBuilder r = null;
             for (int i = 0; i < N; i++) {
                 final ParsedPermissionGroup pg = pkg.getPermissionGroups().get(i);
-                final ParsedPermissionGroup cur = mRegistry.getPermissionGroupLocked(pg.getName());
+                final ParsedPermissionGroup cur = mRegistry.getPermissionGroup(pg.getName());
                 final String curPackageName = (cur == null) ? null : cur.getPackageName();
                 final boolean isPackageUpdate = pg.getPackageName().equals(curPackageName);
                 if (cur == null || isPackageUpdate) {
-                    mRegistry.addPermissionGroupLocked(pg);
+                    mRegistry.addPermissionGroup(pg);
                     if (chatty && DEBUG_PACKAGE_SCANNING) {
                         if (r == null) {
                             r = new StringBuilder(256);
@@ -2491,9 +2502,9 @@
             StringBuilder r = null;
             for (int i=0; i<N; i++) {
                 ParsedPermission p = pkg.getPermissions().get(i);
-                Permission bp = mRegistry.getPermissionLocked(p.getName());
+                Permission bp = mRegistry.getPermission(p.getName());
                 if (bp == null) {
-                    bp = mRegistry.getPermissionTreeLocked(p.getName());
+                    bp = mRegistry.getPermissionTree(p.getName());
                 }
                 if (bp != null && bp.isPermission(p)) {
                     bp.setPermissionInfo(null);
@@ -2508,7 +2519,7 @@
                 }
                 if (p.isAppOp()) {
                     // TODO(zhanghai): Should we just remove the entry for this permission directly?
-                    mRegistry.removeAppOpPermissionPackageLocked(p.getName(), pkg.getPackageName());
+                    mRegistry.removeAppOpPermissionPackage(p.getName(), pkg.getPackageName());
                 }
             }
             if (r != null) {
@@ -2518,9 +2529,11 @@
             N = pkg.getRequestedPermissions().size();
             r = null;
             for (int i=0; i<N; i++) {
-                String perm = pkg.getRequestedPermissions().get(i);
-                if (mRegistry.isPermissionAppOp(perm)) {
-                    mRegistry.removeAppOpPermissionPackageLocked(perm, pkg.getPackageName());
+                final String permissionName = pkg.getRequestedPermissions().get(i);
+                final Permission permission = mRegistry.getPermission(permissionName);
+                if (permission != null && permission.isAppOp()) {
+                    mRegistry.removeAppOpPermissionPackage(permissionName,
+                            pkg.getPackageName());
                 }
             }
             if (r != null) {
@@ -2576,11 +2589,13 @@
 
     @NonNull
     private int[] getPermissionGids(@NonNull String permissionName, @UserIdInt int userId) {
-        Permission permission = mRegistry.getPermission(permissionName);
-        if (permission == null) {
-            return EmptyArray.INT;
+        synchronized (mLock) {
+            Permission permission = mRegistry.getPermission(permissionName);
+            if (permission == null) {
+                return EmptyArray.INT;
+            }
+            return permission.computeGids(userId);
         }
-        return permission.computeGids(userId);
     }
 
     /**
@@ -2629,12 +2644,14 @@
         for (int i = 0; i < requestedPermissionsSize; i++) {
             final String permissionName = pkg.getRequestedPermissions().get(i);
 
-            final Permission permission = mRegistry.getPermission(permissionName);
+            final Permission permission;
+            synchronized (mLock) {
+                permission = mRegistry.getPermission(permissionName);
+            }
             if (permission == null) {
                 continue;
             }
-            if (permission.isSignature() && shouldGrantSignaturePermission(pkg, ps,
-                    permission)) {
+            if (permission.isSignature() && shouldGrantSignaturePermission(pkg, ps, permission)) {
                 shouldGrantSignaturePermission.add(permissionName);
             }
         }
@@ -2716,12 +2733,10 @@
                         // the runtime ones are written only if changed. The only cases of
                         // changed runtime permissions here are promotion of an install to
                         // runtime and revocation of a runtime from a shared user.
-                        synchronized (mLock) {
-                            if (revokeUnusedSharedUserPermissionsLocked(
-                                    ps.getSharedUser().getPackages(), uidState)) {
-                                updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
-                                runtimePermissionsRevoked = true;
-                            }
+                        if (revokeUnusedSharedUserPermissionsLocked(
+                                ps.getSharedUser().getPackages(), uidState)) {
+                            updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
+                            runtimePermissionsRevoked = true;
                         }
                     }
                 }
@@ -2825,7 +2840,7 @@
 
                     // Keep track of app op permissions.
                     if (bp.isAppOp()) {
-                        mRegistry.addAppOpPermissionPackageLocked(perm, pkg.getPackageName());
+                        mRegistry.addAppOpPermissionPackage(perm, pkg.getPackageName());
                     }
 
                     boolean shouldGrantNormalPermission = true;
@@ -3040,6 +3055,7 @@
      *
      * @return The updated value of the {@code updatedUserIds} parameter
      */
+    @GuardedBy("mLock")
     private @NonNull int[] revokePermissionsNoLongerImplicitLocked(@NonNull UidPermissionState ps,
             @NonNull AndroidPackage pkg, int userId, @NonNull int[] updatedUserIds) {
         String pkgName = pkg.getPackageName();
@@ -3048,7 +3064,7 @@
 
         for (String permission : ps.getGrantedPermissions()) {
             if (!pkg.getImplicitPermissions().contains(permission)) {
-                Permission bp = mRegistry.getPermissionLocked(permission);
+                Permission bp = mRegistry.getPermission(permission);
                 if (bp != null && bp.isRuntime()) {
                     int flags = ps.getPermissionFlags(permission);
 
@@ -3092,6 +3108,7 @@
      * @param ps The permission state of the package
      * @param pkg The package requesting the permissions
      */
+    @GuardedBy("mLock")
     private void inheritPermissionStateToNewImplicitPermissionLocked(
             @NonNull ArraySet<String> sourcePerms, @NonNull String newPerm,
             @NonNull UidPermissionState ps, @NonNull AndroidPackage pkg) {
@@ -3122,7 +3139,7 @@
                         + " for " + pkgName);
             }
 
-            ps.grantPermission(mRegistry.getPermissionLocked(newPerm));
+            ps.grantPermission(mRegistry.getPermission(newPerm));
         }
 
         // Add permission flags
@@ -3163,6 +3180,7 @@
      *
      * @return  List of users for which the permission state has been changed
      */
+    @GuardedBy("mLock")
     private @NonNull int[] setInitialGrantForNewImplicitPermissionsLocked(
             @NonNull UidPermissionState origPs, @NonNull UidPermissionState ps,
             @NonNull AndroidPackage pkg, @NonNull ArraySet<String> newImplicitPermissions,
@@ -3197,7 +3215,7 @@
             ArraySet<String> sourcePerms = newToSplitPerms.get(newPerm);
 
             if (sourcePerms != null) {
-                Permission bp = mRegistry.getPermissionLocked(newPerm);
+                Permission bp = mRegistry.getPermission(newPerm);
                 if (bp.isRuntime()) {
 
                     if (!newPerm.equals(Manifest.permission.ACTIVITY_RECOGNITION)) {
@@ -3212,7 +3230,7 @@
                         for (int sourcePermNum = 0; sourcePermNum < sourcePerms.size();
                                 sourcePermNum++) {
                             final String sourcePerm = sourcePerms.valueAt(sourcePermNum);
-                            Permission sourceBp = mRegistry.getPermissionLocked(sourcePerm);
+                            Permission sourceBp = mRegistry.getPermission(sourcePerm);
                             if (!sourceBp.isRuntime()) {
                                 inheritsFromInstallPerm = true;
                                 break;
@@ -3554,11 +3572,13 @@
                         + packageName + " (" + pkg.getPath()
                         + ") not in privapp-permissions whitelist");
                 if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
-                    if (mPrivappPermissionsViolations == null) {
-                        mPrivappPermissionsViolations = new ArraySet<>();
+                    synchronized (mLock) {
+                        if (mPrivappPermissionsViolations == null) {
+                            mPrivappPermissionsViolations = new ArraySet<>();
+                        }
+                        mPrivappPermissionsViolations.add(packageName + " (" + pkg.getPath() + "): "
+                                + permissionName);
                     }
-                    mPrivappPermissionsViolations.add(packageName + " (" + pkg.getPath() + "): "
-                            + permissionName);
                 }
             }
         }
@@ -3662,15 +3682,16 @@
         final boolean instantApp = mPackageManagerInt.isInstantApp(pkg.getPackageName(), userId);
 
         for (String permission : pkg.getRequestedPermissions()) {
-            final Permission bp;
+            final boolean shouldGrantPermission;
             synchronized (mLock) {
-                bp = mRegistry.getPermissionLocked(permission);
+                final Permission bp = mRegistry.getPermission(permission);
+                shouldGrantPermission = bp != null && (bp.isRuntime() || bp.isDevelopment())
+                        && (!instantApp || bp.isInstant())
+                        && (supportsRuntimePermissions || !bp.isRuntimeOnly())
+                        && (grantedPermissions == null
+                                || ArrayUtils.contains(grantedPermissions, permission));
             }
-            if (bp != null && (bp.isRuntime() || bp.isDevelopment())
-                    && (!instantApp || bp.isInstant())
-                    && (supportsRuntimePermissions || !bp.isRuntimeOnly())
-                    && (grantedPermissions == null
-                           || ArrayUtils.contains(grantedPermissions, permission))) {
+            if (shouldGrantPermission) {
                 final int flags = getPermissionFlagsInternal(permission, pkg.getPackageName(),
                         callingUid, userId);
                 if (supportsRuntimePermissions) {
@@ -3704,14 +3725,13 @@
             for (int j = 0; j < permissionCount; j++) {
                 final String permissionName = pkg.getRequestedPermissions().get(j);
 
-                final Permission bp = mRegistry.getPermissionLocked(permissionName);
-
-                if (bp == null || !bp.isHardOrSoftRestricted()) {
-                    continue;
-                }
-
                 final boolean isGranted;
                 synchronized (mLock) {
+                    final Permission bp = mRegistry.getPermission(permissionName);
+                    if (bp == null || !bp.isHardOrSoftRestricted()) {
+                        continue;
+                    }
+
                     final UidPermissionState uidState = getUidStateLocked(pkg, userId);
                     if (uidState == null) {
                         Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()
@@ -3865,11 +3885,6 @@
         int affectedUserId = UserHandle.USER_NULL;
         // Update permissions
         for (String eachPerm : deletedPs.pkg.getRequestedPermissions()) {
-            Permission bp = mRegistry.getPermission(eachPerm);
-            if (bp == null) {
-                continue;
-            }
-
             // Check if another package in the shared user needs the permission.
             boolean used = false;
             final List<AndroidPackage> pkgs = sus.getPackages();
@@ -3913,6 +3928,11 @@
                     continue;
                 }
 
+                Permission bp = mRegistry.getPermission(eachPerm);
+                if (bp == null) {
+                    continue;
+                }
+
                 // TODO(zhanghai): Why are we only killing the UID when GIDs changed, instead of any
                 //  permission change?
                 if (uidState.removePermissionState(bp.getName()) && bp.hasGids()) {
@@ -3939,7 +3959,7 @@
             final int requestedPermCount = pkg.getRequestedPermissions().size();
             for (int j = 0; j < requestedPermCount; j++) {
                 String permission = pkg.getRequestedPermissions().get(j);
-                Permission bp = mRegistry.getPermissionLocked(permission);
+                Permission bp = mRegistry.getPermission(permission);
                 if (bp != null) {
                     usedPermissions.add(permission);
                 }
@@ -3954,7 +3974,7 @@
         for (int i = permissionStatesSize - 1; i >= 0; i--) {
             PermissionState permissionState = permissionStates.get(i);
             if (!usedPermissions.contains(permissionState.getName())) {
-                Permission bp = mRegistry.getPermissionLocked(permissionState.getName());
+                Permission bp = mRegistry.getPermission(permissionState.getName());
                 if (bp != null) {
                     if (uidState.removePermissionState(bp.getName())
                             && permissionState.isRuntime()) {
@@ -4017,35 +4037,6 @@
     }
 
     /**
-     * Cache background->foreground permission mapping.
-     *
-     * <p>This is only run once.
-     */
-    private void cacheBackgroundToForegoundPermissionMapping() {
-        synchronized (mLock) {
-            if (mBackgroundPermissions == null) {
-                // Cache background -> foreground permission mapping.
-                // Only system declares background permissions, hence mapping does never change.
-                mBackgroundPermissions = new ArrayMap<>();
-                for (Permission bp : mRegistry.getPermissionsLocked()) {
-                    if (bp.getBackgroundPermission() != null) {
-                        String fgPerm = bp.getName();
-                        String bgPerm = bp.getBackgroundPermission();
-
-                        List<String> fgPerms = mBackgroundPermissions.get(bgPerm);
-                        if (fgPerms == null) {
-                            fgPerms = new ArrayList<>();
-                            mBackgroundPermissions.put(bgPerm, fgPerms);
-                        }
-
-                        fgPerms.add(fgPerm);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
      * Update all packages on the volume, <u>beside</u> the changing package. If the changing
      * package is set too, all packages are updated.
      */
@@ -4118,8 +4109,6 @@
             flags |= UPDATE_PERMISSIONS_ALL;
         }
 
-        cacheBackgroundToForegoundPermissionMapping();
-
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "restorePermissionState");
         // Now update the permissions for all packages.
         if ((flags & UPDATE_PERMISSIONS_ALL) != 0) {
@@ -4173,9 +4162,9 @@
         boolean changed = false;
         Set<Permission> needsUpdate = null;
         synchronized (mLock) {
-            for (final Permission bp : mRegistry.getPermissionsLocked()) {
+            for (final Permission bp : mRegistry.getPermissions()) {
                 if (bp.isDynamic()) {
-                    bp.updateDynamicPermission(mRegistry.getPermissionTreesLocked());
+                    bp.updateDynamicPermission(mRegistry.getPermissionTrees());
                 }
                 if (!packageName.equals(bp.getPackageName())) {
                     // Not checking sourcePackageSetting because it can be null when
@@ -4225,7 +4214,9 @@
                             }
                         });
                     }
-                    mRegistry.removePermissionLocked(bp.getName());
+                    synchronized (mLock) {
+                        mRegistry.removePermission(bp.getName());
+                    }
                     continue;
                 }
                 final AndroidPackage sourcePkg =
@@ -4239,7 +4230,7 @@
                     }
                     Slog.w(TAG, "Removing dangling permission: " + bp.getName()
                             + " from package " + bp.getPackageName());
-                    mRegistry.removePermissionLocked(bp.getName());
+                    mRegistry.removePermission(bp.getName());
                 }
             }
         }
@@ -4307,7 +4298,7 @@
 
         Set<Permission> needsUpdate = null;
         synchronized (mLock) {
-            final Iterator<Permission> it = mRegistry.getPermissionTreesLocked().iterator();
+            final Iterator<Permission> it = mRegistry.getPermissionTrees().iterator();
             while (it.hasNext()) {
                 final Permission bp = it.next();
                 if (!packageName.equals(bp.getPackageName())) {
@@ -4343,7 +4334,7 @@
                     }
                     Slog.w(TAG, "Removing dangling permission tree: " + bp.getName()
                             + " from package " + bp.getPackageName());
-                    mRegistry.removePermissionLocked(bp.getName());
+                    mRegistry.removePermission(bp.getName());
                 }
             }
         }
@@ -4524,16 +4515,16 @@
         return builder.toString();
     }
 
-    @GuardedBy({"mSettings.mLock", "mLock"})
+    @GuardedBy("mLock")
     private int calculateCurrentPermissionFootprintLocked(@NonNull Permission permissionTree) {
         int size = 0;
-        for (final Permission permission : mRegistry.getPermissionsLocked()) {
+        for (final Permission permission : mRegistry.getPermissions()) {
             size += permissionTree.calculateFootprint(permission);
         }
         return size;
     }
 
-    @GuardedBy({"mSettings.mLock", "mLock"})
+    @GuardedBy("mLock")
     private void enforcePermissionCapLocked(PermissionInfo info, Permission tree) {
         // We calculate the max size of permissions defined by this uid and throw
         // if that plus the size of 'info' would exceed our stated maximum.
@@ -4547,9 +4538,12 @@
 
     private void systemReady() {
         mSystemReady = true;
-        if (mPrivappPermissionsViolations != null) {
-            throw new IllegalStateException("Signature|privileged permissions not in "
-                    + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
+
+        synchronized (mLock) {
+            if (mPrivappPermissionsViolations != null) {
+                throw new IllegalStateException("Signature|privileged permissions not in "
+                        + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
+            }
         }
 
         mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
@@ -4617,29 +4611,21 @@
         mMetricsLogger.write(log);
     }
 
-    /**
-     * Get the mapping of background permissions to their foreground permissions.
-     *
-     * <p>Only initialized in the system server.
-     *
-     * @return the map &lt;bg permission -> list&lt;fg perm&gt;&gt;
-     */
-    public @Nullable ArrayMap<String, List<String>> getBackgroundPermissions() {
-        return mBackgroundPermissions;
-    }
-
+    @GuardedBy("mLock")
     @Nullable
     private UidPermissionState getUidStateLocked(@NonNull PackageSetting ps,
             @UserIdInt int userId) {
         return getUidStateLocked(ps.getAppId(), userId);
     }
 
+    @GuardedBy("mLock")
     @Nullable
     private UidPermissionState getUidStateLocked(@NonNull AndroidPackage pkg,
             @UserIdInt int userId) {
         return getUidStateLocked(pkg.getUid(), userId);
     }
 
+    @GuardedBy("mLock")
     @Nullable
     private UidPermissionState getUidStateLocked(@AppIdInt int appId, @UserIdInt int userId) {
         final UserPermissionState userState = mState.getUserState(userId);
@@ -4682,11 +4668,12 @@
         });
     }
 
+    @GuardedBy("mLock")
     private void readLegacyPermissionStatesLocked(@NonNull UidPermissionState uidState,
             @NonNull Collection<LegacyPermissionState.PermissionState> permissionStates) {
         for (final LegacyPermissionState.PermissionState permissionState : permissionStates) {
             final String permissionName = permissionState.getName();
-            final Permission permission = mRegistry.getPermissionLocked(permissionName);
+            final Permission permission = mRegistry.getPermission(permissionName);
             if (permission == null) {
                 Slog.w(TAG, "Unknown permission: " + permissionName);
                 continue;
@@ -4771,9 +4758,9 @@
                             permission.setGids(configPermission.getRawGids(),
                                     configPermission.areGidsPerUser());
                         }
-                        mRegistry.addPermissionLocked(permission);
+                        mRegistry.addPermission(permission);
                     } else {
-                        mRegistry.addPermissionTreeLocked(permission);
+                        mRegistry.addPermissionTree(permission);
                     }
                 }
             }
@@ -4787,7 +4774,7 @@
             final List<LegacyPermission> legacyPermissions = new ArrayList<>();
             synchronized (mLock) {
                 final Collection<Permission> permissions = writePermissionOrPermissionTree == 0
-                        ? mRegistry.getPermissionsLocked() : mRegistry.getPermissionTreesLocked();
+                        ? mRegistry.getPermissions() : mRegistry.getPermissionTrees();
                 for (final Permission permission : permissions) {
                     // We don't need to provide UID and GIDs, which are only retrieved when dumping.
                     final LegacyPermission legacyPermission = new LegacyPermission(
@@ -4807,7 +4794,7 @@
     private void transferPermissions(@NonNull String oldPackageName,
             @NonNull String newPackageName) {
         synchronized (mLock) {
-            mRegistry.transferPermissionsLocked(oldPackageName, newPackageName);
+            mRegistry.transferPermissions(oldPackageName, newPackageName);
         }
     }
 
@@ -4822,7 +4809,7 @@
     private List<LegacyPermission> getLegacyPermissions() {
         synchronized (mLock) {
             final List<LegacyPermission> legacyPermissions = new ArrayList<>();
-            for (final Permission permission : mRegistry.getPermissionsLocked()) {
+            for (final Permission permission : mRegistry.getPermissions()) {
                 final LegacyPermission legacyPermission = new LegacyPermission(
                         permission.getPermissionInfo(), permission.getType(), permission.getUid(),
                         permission.getRawGids());
@@ -4836,7 +4823,7 @@
     private Map<String, Set<String>> getAllAppOpPermissionPackages() {
         synchronized (mLock) {
             final ArrayMap<String, ArraySet<String>> appOpPermissionPackages =
-                    mRegistry.getAllAppOpPermissionPackagesLocked();
+                    mRegistry.getAllAppOpPermissionPackages();
             final Map<String, Set<String>> deepClone = new ArrayMap<>();
             final int appOpPermissionPackagesSize = appOpPermissionPackages.size();
             for (int i = 0; i < appOpPermissionPackagesSize; i++) {
@@ -5045,8 +5032,8 @@
 
         @Override
         public Permission getPermissionTEMP(String permName) {
-            synchronized (PermissionManagerService.this.mLock) {
-                return mRegistry.getPermissionLocked(permName);
+            synchronized (mLock) {
+                return mRegistry.getPermission(permName);
             }
         }
 
@@ -5056,7 +5043,7 @@
             ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
 
             synchronized (mLock) {
-                for (final Permission permission : mRegistry.getPermissionsLocked()) {
+                for (final Permission permission : mRegistry.getPermissions()) {
                     if (permission.getProtection() == protection) {
                         matchingPermissions.add(permission.generatePermissionInfo(0));
                     }
@@ -5072,7 +5059,7 @@
             ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
 
             synchronized (mLock) {
-                for (final Permission permission : mRegistry.getPermissionsLocked()) {
+                for (final Permission permission : mRegistry.getPermissions()) {
                     if ((permission.getProtectionFlags() & protectionFlags) == protectionFlags) {
                         matchingPermissions.add(permission.generatePermissionInfo(0));
                     }
@@ -5270,7 +5257,7 @@
                 Iterator<String> iterator = permissionNames.iterator();
                 while (iterator.hasNext()) {
                     final String permissionName = iterator.next();
-                    final Permission permission = mRegistry.getPermissionLocked(permissionName);
+                    final Permission permission = mRegistry.getPermission(permissionName);
                     if (permission == null || !permission.isHardOrSoftRestricted()) {
                         iterator.remove();
                     }
@@ -5346,12 +5333,11 @@
             }
         }
 
-        public void addListenerLocked(IOnPermissionsChangeListener listener) {
+        public void addListener(IOnPermissionsChangeListener listener) {
             mPermissionListeners.register(listener);
-
         }
 
-        public void removeListenerLocked(IOnPermissionsChangeListener listener) {
+        public void removeListener(IOnPermissionsChangeListener listener) {
             mPermissionListeners.unregister(listener);
         }
 
diff --git a/services/core/java/com/android/server/pm/permission/PermissionRegistry.java b/services/core/java/com/android/server/pm/permission/PermissionRegistry.java
index 36719203..0e3fda7 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionRegistry.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionRegistry.java
@@ -22,8 +22,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
-import com.android.internal.annotations.GuardedBy;
-
 import java.util.Collection;
 
 /**
@@ -34,87 +32,62 @@
      * All of the permissions known to the system. The mapping is from permission
      * name to permission object.
      */
-    @GuardedBy("mLock")
     private final ArrayMap<String, Permission> mPermissions = new ArrayMap<>();
 
     /**
      * All permission trees known to the system. The mapping is from permission tree
      * name to permission object.
      */
-    @GuardedBy("mLock")
     private final ArrayMap<String, Permission> mPermissionTrees = new ArrayMap<>();
 
     /**
      * All permisson groups know to the system. The mapping is from permission group
      * name to permission group object.
      */
-    @GuardedBy("mLock")
     private final ArrayMap<String, ParsedPermissionGroup> mPermissionGroups = new ArrayMap<>();
 
     /**
      * Set of packages that request a particular app op. The mapping is from permission
      * name to package names.
      */
-    @GuardedBy("mLock")
     private final ArrayMap<String, ArraySet<String>> mAppOpPermissionPackages = new ArrayMap<>();
 
     @NonNull
-    private final Object mLock;
-
-    public PermissionRegistry(@NonNull Object lock) {
-        mLock = lock;
-    }
-
-    @GuardedBy("mLock")
-    @NonNull
-    public Collection<Permission> getPermissionsLocked() {
+    public Collection<Permission> getPermissions() {
         return mPermissions.values();
     }
 
-    @GuardedBy("mLock")
-    @Nullable
-    public Permission getPermissionLocked(@NonNull String permName) {
-        return mPermissions.get(permName);
-    }
-
     @Nullable
     public Permission getPermission(@NonNull String permissionName) {
-        synchronized (mLock) {
-            return getPermissionLocked(permissionName);
-        }
+        return mPermissions.get(permissionName);
     }
 
-    @GuardedBy("mLock")
-    public void addPermissionLocked(@NonNull Permission permission) {
+    public void addPermission(@NonNull Permission permission) {
         mPermissions.put(permission.getName(), permission);
     }
 
-    @GuardedBy("mLock")
-    public void removePermissionLocked(@NonNull String permissionName) {
+    public void removePermission(@NonNull String permissionName) {
         mPermissions.remove(permissionName);
     }
 
-    @GuardedBy("mLock")
     @NonNull
-    public Collection<Permission> getPermissionTreesLocked() {
+    public Collection<Permission> getPermissionTrees() {
         return mPermissionTrees.values();
     }
 
-    @GuardedBy("mLock")
     @Nullable
-    public Permission getPermissionTreeLocked(@NonNull String permissionTreeName) {
+    public Permission getPermissionTree(@NonNull String permissionTreeName) {
         return mPermissionTrees.get(permissionTreeName);
     }
 
-    @GuardedBy("mLock")
-    public void addPermissionTreeLocked(@NonNull Permission permissionTree) {
+    public void addPermissionTree(@NonNull Permission permissionTree) {
         mPermissionTrees.put(permissionTree.getName(), permissionTree);
     }
 
     /**
      * Transfers ownership of permissions from one package to another.
      */
-    public void transferPermissionsLocked(@NonNull String oldPackageName,
+    public void transferPermissions(@NonNull String oldPackageName,
             @NonNull String newPackageName) {
         for (int i = 0; i < 2; i++) {
             ArrayMap<String, Permission> permissions = i == 0 ? mPermissionTrees : mPermissions;
@@ -124,37 +97,31 @@
         }
     }
 
-    @GuardedBy("mLock")
     @NonNull
-    public Collection<ParsedPermissionGroup> getPermissionGroupsLocked() {
+    public Collection<ParsedPermissionGroup> getPermissionGroups() {
         return mPermissionGroups.values();
     }
 
-    @GuardedBy("mLock")
     @Nullable
-    public ParsedPermissionGroup getPermissionGroupLocked(@NonNull String permissionGroupName) {
+    public ParsedPermissionGroup getPermissionGroup(@NonNull String permissionGroupName) {
         return mPermissionGroups.get(permissionGroupName);
     }
 
-    @GuardedBy("mLock")
-    public void addPermissionGroupLocked(@NonNull ParsedPermissionGroup permissionGroup) {
+    public void addPermissionGroup(@NonNull ParsedPermissionGroup permissionGroup) {
         mPermissionGroups.put(permissionGroup.getName(), permissionGroup);
     }
 
-    @GuardedBy("mLock")
     @NonNull
-    public ArrayMap<String, ArraySet<String>> getAllAppOpPermissionPackagesLocked() {
+    public ArrayMap<String, ArraySet<String>> getAllAppOpPermissionPackages() {
         return mAppOpPermissionPackages;
     }
 
-    @GuardedBy("mLock")
     @Nullable
-    public ArraySet<String> getAppOpPermissionPackagesLocked(@NonNull String permissionName) {
+    public ArraySet<String> getAppOpPermissionPackages(@NonNull String permissionName) {
         return mAppOpPermissionPackages.get(permissionName);
     }
 
-    @GuardedBy("mLock")
-    public void addAppOpPermissionPackageLocked(@NonNull String permissionName,
+    public void addAppOpPermissionPackage(@NonNull String permissionName,
             @NonNull String packageName) {
         ArraySet<String> packageNames = mAppOpPermissionPackages.get(permissionName);
         if (packageNames == null) {
@@ -164,8 +131,7 @@
         packageNames.add(packageName);
     }
 
-    @GuardedBy("mLock")
-    public void removeAppOpPermissionPackageLocked(@NonNull String permissionName,
+    public void removeAppOpPermissionPackage(@NonNull String permissionName,
             @NonNull String packageName) {
         final ArraySet<String> packageNames = mAppOpPermissionPackages.get(permissionName);
         if (packageNames == null) {
@@ -184,23 +150,7 @@
      */
     @NonNull
     public Permission enforcePermissionTree(@NonNull String permissionName, int callingUid) {
-        synchronized (mLock) {
-            return Permission.enforcePermissionTree(mPermissionTrees.values(), permissionName,
-                    callingUid);
-        }
-    }
-
-    public boolean isPermissionInstant(@NonNull String permissionName) {
-        synchronized (mLock) {
-            final Permission permission = mPermissions.get(permissionName);
-            return permission != null && permission.isInstant();
-        }
-    }
-
-    boolean isPermissionAppOp(@NonNull String permissionName) {
-        synchronized (mLock) {
-            final Permission permission = mPermissions.get(permissionName);
-            return permission != null && permission.isAppOp();
-        }
+        return Permission.enforcePermissionTree(mPermissionTrees.values(), permissionName,
+                callingUid);
     }
 }
diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java
index f8e26fc..b007a75 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldController.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldController.java
@@ -16,8 +16,10 @@
 
 package com.android.server.policy;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Rect;
+import android.hardware.ICameraService;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
@@ -26,11 +28,13 @@
 import android.os.Handler;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.util.Slog;
 import android.view.DisplayInfo;
 import android.view.IDisplayFoldListener;
 
 import com.android.server.DisplayThread;
 import com.android.server.LocalServices;
+import com.android.server.camera.CameraServiceProxy;
 import com.android.server.wm.WindowManagerInternal;
 
 /**
@@ -38,11 +42,13 @@
  * TODO(b/126160895): Move DisplayFoldController from PhoneWindowManager to DisplayPolicy.
  */
 class DisplayFoldController {
-
     private static final String TAG = "DisplayFoldController";
 
     private final WindowManagerInternal mWindowManagerInternal;
     private final DisplayManagerInternal mDisplayManagerInternal;
+    // Camera service proxy can be disabled through a config.
+    @Nullable
+    private final CameraServiceProxy mCameraServiceProxy;
     private final int mDisplayId;
     private final Handler mHandler;
 
@@ -58,10 +64,12 @@
     private final DisplayFoldDurationLogger mDurationLogger = new DisplayFoldDurationLogger();
 
     DisplayFoldController(WindowManagerInternal windowManagerInternal,
-            DisplayManagerInternal displayManagerInternal, int displayId, Rect foldedArea,
+            DisplayManagerInternal displayManagerInternal,
+            @Nullable CameraServiceProxy cameraServiceProxy, int displayId, Rect foldedArea,
             Handler handler) {
         mWindowManagerInternal = windowManagerInternal;
         mDisplayManagerInternal = displayManagerInternal;
+        mCameraServiceProxy = cameraServiceProxy;
         mDisplayId = displayId;
         mFoldedArea = new Rect(foldedArea);
         mHandler = handler;
@@ -116,6 +124,16 @@
             }
         }
 
+        if (mCameraServiceProxy != null) {
+            if (folded) {
+                mCameraServiceProxy.setDeviceStateFlags(ICameraService.DEVICE_STATE_FOLDED);
+            } else {
+                mCameraServiceProxy.clearDeviceStateFlags(ICameraService.DEVICE_STATE_FOLDED);
+            }
+        } else {
+            Slog.w(TAG, "Camera service unavailable to toggle folded state.");
+        }
+
         mDurationLogger.setDeviceFolded(folded);
         mDurationLogger.logFocusedAppWithFoldState(folded, mFocusedApp);
         mFolded = folded;
@@ -193,8 +211,13 @@
     }
 
     static DisplayFoldController create(Context context, int displayId) {
+        final WindowManagerInternal windowManagerService =
+                LocalServices.getService(WindowManagerInternal.class);
         final DisplayManagerInternal displayService =
                 LocalServices.getService(DisplayManagerInternal.class);
+        final CameraServiceProxy cameraServiceProxy =
+                LocalServices.getService(CameraServiceProxy.class);
+
         final String configFoldedArea = context.getResources().getString(
                 com.android.internal.R.string.config_foldedArea);
         final Rect foldedArea;
@@ -204,7 +227,7 @@
             foldedArea = Rect.unflattenFromString(configFoldedArea);
         }
 
-        return new DisplayFoldController(LocalServices.getService(WindowManagerInternal.class),
-                displayService, displayId, foldedArea, DisplayThread.getHandler());
+        return new DisplayFoldController(windowManagerService, displayService, cameraServiceProxy,
+                displayId, foldedArea, DisplayThread.getHandler());
     }
 }
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index 06edd19..1a4a222 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -18,6 +18,7 @@
 
 import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.SynchronousUserSwitchObserver;
 import android.attention.AttentionManagerInternal;
@@ -42,6 +43,7 @@
 import com.android.server.wm.WindowManagerInternal;
 
 import java.io.PrintWriter;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 
@@ -66,6 +68,9 @@
     /** Default value in absence of {@link DeviceConfig} override. */
     static final long DEFAULT_PRE_DIM_CHECK_DURATION_MILLIS = 2_000;
 
+    @VisibleForTesting
+    protected long mPreDimCheckDurationMillis;
+
     /** DeviceConfig flag name, describes how long to run the check beyond the screen dim event. */
     static final String KEY_POST_DIM_CHECK_DURATION_MILLIS =
             "post_dim_check_duration_millis";
@@ -73,12 +78,28 @@
     /** Default value in absence of {@link DeviceConfig} override. */
     static final long DEFAULT_POST_DIM_CHECK_DURATION_MILLIS = 0;
 
+    private long mRequestedPostDimTimeoutMillis;
+
+    /**
+     * Keep the last used post dim timeout for the dumpsys (it can't be longer the dim duration).
+     */
+    private long mEffectivePostDimTimeoutMillis;
+
     /**
      * DeviceConfig flag name, describes the limit of how long the device can remain unlocked due to
      * attention checking.
      */
     static final String KEY_MAX_EXTENSION_MILLIS = "max_extension_millis";
 
+    /**
+     * The default value for the maximum time, in millis, that the phone can stay unlocked because
+     * of attention events, triggered by any user.
+     */
+    @VisibleForTesting
+    protected long mDefaultMaximumExtensionMillis;
+
+    private long mMaximumExtensionMillis;
+
     private Context mContext;
 
     private boolean mIsSettingEnabled;
@@ -88,13 +109,6 @@
      */
     private final Runnable mOnUserAttention;
 
-    /**
-     * The default value for the maximum time, in millis, that the phone can stay unlocked because
-     * of attention events, triggered by any user.
-     */
-    @VisibleForTesting
-    protected long mDefaultMaximumExtensionMillis;
-
     private final Object mLock;
 
     /**
@@ -137,9 +151,6 @@
     @VisibleForTesting
     AttentionCallbackInternalImpl mCallback;
 
-    /** Keep the last used post dim timeout for the dumpsys. */
-    private long mLastPostDimTimeout;
-
     public AttentionDetector(Runnable onUserAttention, Object lock) {
         mOnUserAttention = onUserAttention;
         mLock = lock;
@@ -180,6 +191,11 @@
                         updateEnabledFromSettings(context);
                     }
                 }, UserHandle.USER_ALL);
+
+        readValuesFromDeviceConfig();
+        DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+                context.getMainExecutor(),
+                (properties) -> onDeviceConfigChange(properties.getKeyset()));
     }
 
     /** To be called in {@link PowerManagerService#updateUserActivitySummaryLocked}. */
@@ -192,8 +208,8 @@
         }
 
         final long now = SystemClock.uptimeMillis();
-        final long whenToCheck = nextScreenDimming - getPreDimCheckDurationMillis();
-        final long whenToStopExtending = mLastUserActivityTime + getMaxExtensionMillis();
+        final long whenToCheck = nextScreenDimming - mPreDimCheckDurationMillis;
+        final long whenToStopExtending = mLastUserActivityTime + mMaximumExtensionMillis;
         if (now < whenToCheck) {
             if (DEBUG) {
                 Slog.d(TAG, "Do not check for attention yet, wait " + (whenToCheck - now));
@@ -220,9 +236,11 @@
         mRequestId++;
         mLastActedOnNextScreenDimming = nextScreenDimming;
         mCallback = new AttentionCallbackInternalImpl(mRequestId);
+        mEffectivePostDimTimeoutMillis = Math.min(mRequestedPostDimTimeoutMillis,
+                dimDurationMillis);
         Slog.v(TAG, "Checking user attention, ID: " + mRequestId);
         final boolean sent = mAttentionManager.checkAttention(
-                getPreDimCheckDurationMillis() + getPostDimCheckDurationMillis(dimDurationMillis),
+                mPreDimCheckDurationMillis + mEffectivePostDimTimeoutMillis,
                 mCallback);
         if (!sent) {
             mRequested.set(false);
@@ -294,9 +312,9 @@
     public void dump(PrintWriter pw) {
         pw.println("AttentionDetector:");
         pw.println(" mIsSettingEnabled=" + mIsSettingEnabled);
-        pw.println(" mMaxExtensionMillis=" + getMaxExtensionMillis());
-        pw.println(" preDimCheckDurationMillis=" + getPreDimCheckDurationMillis());
-        pw.println(" postDimCheckDurationMillis=" + mLastPostDimTimeout);
+        pw.println(" mMaxExtensionMillis=" + mMaximumExtensionMillis);
+        pw.println(" mPreDimCheckDurationMillis=" + mPreDimCheckDurationMillis);
+        pw.println(" mEffectivePostDimTimeout=" + mEffectivePostDimTimeoutMillis);
         pw.println(" mLastUserActivityTime(excludingAttention)=" + mLastUserActivityTime);
         pw.println(" mAttentionServiceSupported=" + isAttentionServiceSupported());
         pw.println(" mRequested=" + mRequested);
@@ -319,7 +337,7 @@
 
     /** How long to check <b>after</b> the screen dims, capped at the dim duration. */
     @VisibleForTesting
-    protected long getPostDimCheckDurationMillis(long dimDurationMillis) {
+    protected long getPostDimCheckDurationMillis() {
         final long millis = DeviceConfig.getLong(NAMESPACE_ATTENTION_MANAGER_SERVICE,
                 KEY_POST_DIM_CHECK_DURATION_MILLIS,
                 DEFAULT_POST_DIM_CHECK_DURATION_MILLIS);
@@ -328,9 +346,7 @@
             Slog.w(TAG, "Bad flag value supplied for: " + KEY_POST_DIM_CHECK_DURATION_MILLIS);
             return DEFAULT_POST_DIM_CHECK_DURATION_MILLIS;
         }
-
-        mLastPostDimTimeout = Math.min(millis, dimDurationMillis);
-        return mLastPostDimTimeout;
+        return millis;
     }
 
     /** How long the device can remain unlocked due to attention checking. */
@@ -348,6 +364,32 @@
         return millis;
     }
 
+    private void onDeviceConfigChange(@NonNull Set<String> keys) {
+        for (String key : keys) {
+            switch (key) {
+                case KEY_MAX_EXTENSION_MILLIS:
+                case KEY_POST_DIM_CHECK_DURATION_MILLIS:
+                case KEY_PRE_DIM_CHECK_DURATION_MILLIS:
+                    readValuesFromDeviceConfig();
+                    return;
+                default:
+                    Slog.i(TAG, "Ignoring change on " + key);
+            }
+        }
+    }
+
+    private void readValuesFromDeviceConfig() {
+        mMaximumExtensionMillis = getMaxExtensionMillis();
+        mPreDimCheckDurationMillis = getPreDimCheckDurationMillis();
+        mRequestedPostDimTimeoutMillis = getPostDimCheckDurationMillis();
+
+        Slog.i(TAG, "readValuesFromDeviceConfig():"
+                + "\nmMaximumExtensionMillis=" + mMaximumExtensionMillis
+                + "\nmPreDimCheckDurationMillis=" + mPreDimCheckDurationMillis
+                + "\nmRequestedPostDimTimeoutMillis=" + mRequestedPostDimTimeoutMillis);
+
+    }
+
     @VisibleForTesting
     final class AttentionCallbackInternalImpl extends AttentionCallbackInternal {
         private final int mId;
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 7433a3a..d3b1ac6 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -247,6 +247,13 @@
     // 20% as a conservative estimate.
     private static final int MAX_PROCSTATS_RAW_SHARD_SIZE = (int) (MAX_PROCSTATS_SHARD_SIZE * 1.20);
 
+    /**
+     * Threshold to filter out small CPU times at frequency per UID. Those small values appear
+     * because of more precise accounting in a BPF program. Discarding them reduces the data by at
+     * least 20% with negligible error.
+     */
+    private static final int MIN_CPU_TIME_PER_UID_FREQ = 10;
+
     private final Object mThermalLock = new Object();
     @GuardedBy("mThermalLock")
     private IThermalService mThermalService;
@@ -1509,7 +1516,7 @@
     int pullCpuTimePerUidFreqLocked(int atomTag, List<StatsEvent> pulledData) {
         mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
             for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
-                if (cpuFreqTimeMs[freqIndex] != 0) {
+                if (cpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) {
                     pulledData.add(FrameworkStatsLog.buildStatsEvent(
                             atomTag, uid, freqIndex, cpuFreqTimeMs[freqIndex]));
                 }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c51e63f..9273bf7 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -125,7 +125,6 @@
 import static com.android.server.wm.Task.ActivityState.PAUSING;
 import static com.android.server.wm.Task.ActivityState.RESUMED;
 import static com.android.server.wm.Task.ActivityState.STARTED;
-import static com.android.server.wm.Task.ActivityState.STOPPED;
 import static com.android.server.wm.Task.ActivityState.STOPPING;
 import static com.android.server.wm.TaskProto.ACTIVITY_TYPE;
 import static com.android.server.wm.TaskProto.BOUNDS;
@@ -4127,6 +4126,10 @@
         forAllActivities(r -> {
             info.addLaunchCookie(r.mLaunchCookie);
         });
+        final Task rootTask = getRootTask();
+        info.parentTaskId = rootTask == getParent() && rootTask.mCreatedByOrganizer
+                ? rootTask.mTaskId
+                : INVALID_TASK_ID;
     }
 
     @Nullable PictureInPictureParams getPictureInPictureParams() {
@@ -4843,6 +4846,17 @@
         return mTaskOrganizer != null;
     }
 
+    private boolean canBeOrganized() {
+        // All root tasks can be organized
+        if (isRootTask()) {
+            return true;
+        }
+
+        // Task could be organized if it's the direct child of the root created by organizer.
+        final Task rootTask = getRootTask();
+        return rootTask == getParent() && rootTask.mCreatedByOrganizer;
+    }
+
     @Override
     boolean showSurfaceOnCreation() {
         // Organized tasks handle their own surface visibility
@@ -4991,7 +5005,7 @@
             // is created.
             return false;
         }
-        if (!isRootTask()) {
+        if (!canBeOrganized()) {
             return setTaskOrganizer(null);
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 084b766..c806c94 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1218,9 +1218,9 @@
         mAnimator = new WindowAnimator(this);
         mRoot = new RootWindowContainer(this);
 
-        mUseBLAST = DeviceConfig.getBoolean(
-                    DeviceConfig.NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT,
-                    WM_USE_BLAST_ADAPTER_FLAG, false);
+        final ContentResolver resolver = context.getContentResolver();
+        mUseBLAST = Settings.Global.getInt(resolver,
+            Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_VR, 1) == 1;
 
         mSyncEngine = new BLASTSyncEngine(this);
 
@@ -1298,7 +1298,6 @@
             }
         }, UserHandle.ALL, suspendPackagesFilter, null, null);
 
-        final ContentResolver resolver = context.getContentResolver();
         // Get persisted window scale setting
         mWindowAnimationScaleSetting = Settings.Global.getFloat(resolver,
                 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 51857dc..7d54ea9 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -104,13 +104,55 @@
 
     @Override
     public void applyTransaction(WindowContainerTransaction t) {
-        applyTransaction(t, null /*callback*/, null /*transition*/);
+        enforceTaskPermission("applyTransaction()");
+        if (t == null) {
+            throw new IllegalArgumentException("Null transaction passed to applySyncTransaction");
+        }
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mGlobalLock) {
+                applyTransaction(t, -1 /*syncId*/, null /*transition*/);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     @Override
     public int applySyncTransaction(WindowContainerTransaction t,
             IWindowContainerTransactionCallback callback) {
-        return applyTransaction(t, callback, null /*transition*/);
+        enforceTaskPermission("applySyncTransaction()");
+        if (t == null) {
+            throw new IllegalArgumentException("Null transaction passed to applySyncTransaction");
+        }
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mGlobalLock) {
+                /**
+                 * If callback is non-null we are looking to synchronize this transaction by
+                 * collecting all the results in to a SurfaceFlinger transaction and then delivering
+                 * that to the given transaction ready callback. See {@link BLASTSyncEngine} for the
+                 * details of the operation. But at a high level we create a sync operation with a
+                 * given ID and an associated callback. Then we notify each WindowContainer in this
+                 * WindowContainer transaction that it is participating in a sync operation with
+                 * that ID. Once everything is notified we tell the BLASTSyncEngine "setSyncReady"
+                 * which means that we have added everything to the set. At any point after this,
+                 * all the WindowContainers will eventually finish applying their changes and notify
+                 * the BLASTSyncEngine which will deliver the Transaction to the callback.
+                 */
+                int syncId = -1;
+                if (callback != null) {
+                    syncId = startSyncWithOrganizer(callback);
+                }
+                applyTransaction(t, syncId, null /*transition*/);
+                if (syncId >= 0) {
+                    setSyncReady(syncId);
+                }
+                return syncId;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
     @Override
@@ -131,7 +173,7 @@
                 if (t == null) {
                     t = new WindowContainerTransaction();
                 }
-                applyTransaction(t, null /*callback*/, transition);
+                applyTransaction(t, -1 /*syncId*/, transition);
                 return transition;
             }
         } finally {
@@ -148,10 +190,16 @@
         try {
             synchronized (mGlobalLock) {
                 int syncId = -1;
-                if (t != null) {
-                    syncId = applyTransaction(t, callback, null /*transition*/);
+                if (t != null && callback != null) {
+                    syncId = startSyncWithOrganizer(callback);
                 }
                 getTransitionController().finishTransition(transitionToken);
+                if (t != null) {
+                    applyTransaction(t, syncId, null /*transition*/);
+                }
+                if (syncId >= 0) {
+                    setSyncReady(syncId);
+                }
                 return syncId;
             }
         } finally {
@@ -160,154 +208,114 @@
     }
 
     /**
-     * @param callback If non-null, this will be a sync-transaction.
+     * @param syncId If non-null, this will be a sync-transaction.
      * @param transition A transition to collect changes into.
-     * @return a BLAST sync-id if this is a non-transition, sync transaction.
      */
-    private int applyTransaction(@NonNull WindowContainerTransaction t,
-            @Nullable IWindowContainerTransactionCallback callback,
+    private void applyTransaction(@NonNull WindowContainerTransaction t, int syncId,
             @Nullable Transition transition) {
-        enforceTaskPermission("applySyncTransaction()");
-        int syncId = -1;
-        if (t == null) {
-            throw new IllegalArgumentException(
-                    "Null transaction passed to applySyncTransaction");
-        }
-        final long ident = Binder.clearCallingIdentity();
+        int effects = 0;
+        ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d", syncId);
+        mService.deferWindowLayout();
         try {
-            synchronized (mGlobalLock) {
-                int effects = 0;
-
-                /**
-                 * If callback is non-null we are looking to synchronize this transaction by
-                 * collecting all the results in to a SurfaceFlinger transaction and then delivering
-                 * that to the given transaction ready callback. See {@link BLASTSyncEngine} for the
-                 * details of the operation. But at a high level we create a sync operation with a
-                 * given ID and an associated callback. Then we notify each WindowContainer in this
-                 * WindowContainer transaction that it is participating in a sync operation with
-                 * that ID. Once everything is notified we tell the BLASTSyncEngine "setSyncReady"
-                 * which means that we have added everything to the set. At any point after this,
-                 * all the WindowContainers will eventually finish applying their changes and notify
-                 * the BLASTSyncEngine which will deliver the Transaction to the callback.
-                 */
-                if (callback != null) {
-                    syncId = startSyncWithOrganizer(callback);
+            ArraySet<WindowContainer> haveConfigChanges = new ArraySet<>();
+            Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
+                    t.getChanges().entrySet().iterator();
+            while (entries.hasNext()) {
+                final Map.Entry<IBinder, WindowContainerTransaction.Change> entry = entries.next();
+                final WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
+                if (wc == null || !wc.isAttached()) {
+                    Slog.e(TAG, "Attempt to operate on detached container: " + wc);
+                    continue;
                 }
-                ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d",
-                        syncId);
-                mService.deferWindowLayout();
-                try {
-                    ArraySet<WindowContainer> haveConfigChanges = new ArraySet<>();
-                    Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
-                            t.getChanges().entrySet().iterator();
-                    while (entries.hasNext()) {
-                        final Map.Entry<IBinder, WindowContainerTransaction.Change> entry =
-                                entries.next();
-                        final WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
-                        if (wc == null || !wc.isAttached()) {
-                            Slog.e(TAG, "Attempt to operate on detached container: " + wc);
-                            continue;
-                        }
-                        // Make sure we add to the syncSet before performing
-                        // operations so we don't end up splitting effects between the WM
-                        // pending transaction and the BLASTSync transaction.
-                        if (syncId >= 0) {
-                            addToSyncSet(syncId, wc);
-                        }
+                // Make sure we add to the syncSet before performing
+                // operations so we don't end up splitting effects between the WM
+                // pending transaction and the BLASTSync transaction.
+                if (syncId >= 0) {
+                    addToSyncSet(syncId, wc);
+                }
 
-                        int containerEffect = applyWindowContainerChange(wc, entry.getValue());
-                        if (transition != null) transition.collect(wc);
-                        effects |= containerEffect;
+                int containerEffect = applyWindowContainerChange(wc, entry.getValue());
+                if (transition != null) transition.collect(wc);
+                effects |= containerEffect;
 
-                        // Lifecycle changes will trigger ensureConfig for everything.
-                        if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0
-                                && (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
-                            haveConfigChanges.add(wc);
-                        }
-                    }
-                    // Hierarchy changes
-                    final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
-                    for (int i = 0, n = hops.size(); i < n; ++i) {
-                        final WindowContainerTransaction.HierarchyOp hop = hops.get(i);
-                        final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
-                        if (!wc.isAttached()) {
-                            Slog.e(TAG, "Attempt to operate on detached container: " + wc);
-                            continue;
-                        }
-                        if (syncId >= 0) {
-                            addToSyncSet(syncId, wc);
-                        }
+                // Lifecycle changes will trigger ensureConfig for everything.
+                if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0
+                        && (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
+                    haveConfigChanges.add(wc);
+                }
+            }
+            // Hierarchy changes
+            final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
+            for (int i = 0, n = hops.size(); i < n; ++i) {
+                final WindowContainerTransaction.HierarchyOp hop = hops.get(i);
+                final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
+                if (!wc.isAttached()) {
+                    Slog.e(TAG, "Attempt to operate on detached container: " + wc);
+                    continue;
+                }
+                if (syncId >= 0) {
+                    addToSyncSet(syncId, wc);
+                }
                         effects |= sanitizeAndApplyHierarchyOp(wc, hop);
-                        if (transition != null) {
-                            transition.collect(wc);
-                            if (hop.isReparent() && hop.getNewParent() != null) {
-                                transition.collect(WindowContainer.fromBinder(hop.getNewParent()));
-                            }
-                        }
-                    }
-                    // Queue-up bounds-change transactions for tasks which are now organized. Do
-                    // this after hierarchy ops so we have the final organized state.
-                    entries = t.getChanges().entrySet().iterator();
-                    while (entries.hasNext()) {
-                        final Map.Entry<IBinder, WindowContainerTransaction.Change> entry =
-                                entries.next();
-                        final Task task = WindowContainer.fromBinder(entry.getKey()).asTask();
-                        final Rect surfaceBounds = entry.getValue().getBoundsChangeSurfaceBounds();
-                        if (task == null || !task.isAttached() || surfaceBounds == null) {
-                            continue;
-                        }
-                        if (!task.isOrganized()) {
-                            final Task parent =
-                                    task.getParent() != null ? task.getParent().asTask() : null;
-                            // Also allow direct children of created-by-organizer tasks to be
-                            // controlled. In the future, these will become organized anyways.
-                            if (parent == null || !parent.mCreatedByOrganizer) {
-                                throw new IllegalArgumentException(
-                                        "Can't manipulate non-organized task surface " + task);
-                            }
-                        }
-                        final SurfaceControl.Transaction sft = new SurfaceControl.Transaction();
-                        final SurfaceControl sc = task.getSurfaceControl();
-                        sft.setPosition(sc, surfaceBounds.left, surfaceBounds.top);
-                        if (surfaceBounds.isEmpty()) {
-                            sft.setWindowCrop(sc, null);
-                        } else {
-                            sft.setWindowCrop(sc, surfaceBounds.width(), surfaceBounds.height());
-                        }
-                        task.setMainWindowSizeChangeTransaction(sft);
-                    }
-                    if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
-                        // Already calls ensureActivityConfig
-                        mService.mRootWindowContainer.ensureActivitiesVisible(
-                                null, 0, PRESERVE_WINDOWS);
-                    } else if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
-                        final PooledConsumer f = PooledLambda.obtainConsumer(
-                                ActivityRecord::ensureActivityConfiguration,
-                                PooledLambda.__(ActivityRecord.class), 0,
-                                true /* preserveWindow */);
-                        try {
-                            for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
-                                haveConfigChanges.valueAt(i).forAllActivities(f);
-                            }
-                        } finally {
-                            f.recycle();
-                        }
-                    }
-
-                    if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) == 0) {
-                        mService.addWindowLayoutReasons(LAYOUT_REASON_CONFIG_CHANGED);
-                    }
-                } finally {
-                    mService.continueWindowLayout();
-                    if (syncId >= 0) {
-                        setSyncReady(syncId);
+                if (transition != null) {
+                    transition.collect(wc);
+                    if (hop.isReparent() && hop.getNewParent() != null) {
+                        transition.collect(WindowContainer.fromBinder(hop.getNewParent()));
                     }
                 }
             }
+            // Queue-up bounds-change transactions for tasks which are now organized. Do
+            // this after hierarchy ops so we have the final organized state.
+            entries = t.getChanges().entrySet().iterator();
+            while (entries.hasNext()) {
+                final Map.Entry<IBinder, WindowContainerTransaction.Change> entry = entries.next();
+                final Task task = WindowContainer.fromBinder(entry.getKey()).asTask();
+                final Rect surfaceBounds = entry.getValue().getBoundsChangeSurfaceBounds();
+                if (task == null || !task.isAttached() || surfaceBounds == null) {
+                    continue;
+                }
+                if (!task.isOrganized()) {
+                    final Task parent = task.getParent() != null ? task.getParent().asTask() : null;
+                    // Also allow direct children of created-by-organizer tasks to be
+                    // controlled. In the future, these will become organized anyways.
+                    if (parent == null || !parent.mCreatedByOrganizer) {
+                        throw new IllegalArgumentException(
+                                "Can't manipulate non-organized task surface " + task);
+                    }
+                }
+                final SurfaceControl.Transaction sft = new SurfaceControl.Transaction();
+                final SurfaceControl sc = task.getSurfaceControl();
+                sft.setPosition(sc, surfaceBounds.left, surfaceBounds.top);
+                if (surfaceBounds.isEmpty()) {
+                    sft.setWindowCrop(sc, null);
+                } else {
+                    sft.setWindowCrop(sc, surfaceBounds.width(), surfaceBounds.height());
+                }
+                task.setMainWindowSizeChangeTransaction(sft);
+            }
+            if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
+                // Already calls ensureActivityConfig
+                mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+            } else if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
+                final PooledConsumer f = PooledLambda.obtainConsumer(
+                        ActivityRecord::ensureActivityConfiguration,
+                        PooledLambda.__(ActivityRecord.class), 0,
+                        true /* preserveWindow */);
+                try {
+                    for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
+                        haveConfigChanges.valueAt(i).forAllActivities(f);
+                    }
+                } finally {
+                    f.recycle();
+                }
+            }
+
+            if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) == 0) {
+                mService.addWindowLayoutReasons(LAYOUT_REASON_CONFIG_CHANGED);
+            }
         } finally {
-            Binder.restoreCallingIdentity(ident);
+            mService.continueWindowLayout();
         }
-        return syncId;
     }
 
     private int applyChanges(WindowContainer container, WindowContainerTransaction.Change change) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 4d553e2..3bfcb6d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4255,18 +4255,18 @@
                         mInjector.getPackageManager().getPackagesForUid(
                                 mInjector.binderGetCallingUid()))
                 .write();
-        final int callingUserId = mInjector.userHandleGetCallingUserId();
+        final CallerIdentity caller = getCallerIdentity();
 
-        if (parent) {
-            enforceProfileOwnerOrSystemUser();
-        }
-        enforceUserUnlocked(callingUserId);
+        Preconditions.checkCallAuthorization(!parent || (isDeviceOwner(caller)
+                        || isProfileOwner(caller) || isSystemUid(caller)),
+                "Only profile owner, device owner and system may call this method.");
+        enforceUserUnlocked(caller.getUserId());
         mContext.enforceCallingOrSelfPermission(
                 REQUEST_PASSWORD_COMPLEXITY,
                 "Must have " + REQUEST_PASSWORD_COMPLEXITY + " permission.");
 
         synchronized (getLockObject()) {
-            final int credentialOwner = getCredentialOwner(callingUserId, parent);
+            final int credentialOwner = getCredentialOwner(caller.getUserId(), parent);
             PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(credentialOwner);
             return metrics == null ? PASSWORD_COMPLEXITY_NONE : metrics.determineComplexity();
         }
@@ -7299,7 +7299,8 @@
 
     @Override
     public boolean hasDeviceOwner() {
-        enforceDeviceOwnerOrManageUsers();
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
         return mOwners.hasDeviceOwner();
     }
 
@@ -8355,32 +8356,6 @@
                 || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS);
     }
 
-    private void enforceDeviceOwnerOrManageUsers() {
-        final CallerIdentity caller = getCallerIdentity();
-        if (isDeviceOwner(caller)) {
-            return;
-        }
-        Preconditions.checkCallAuthorization(canManageUsers(caller));
-    }
-
-    private void enforceProfileOwnerOrSystemUser() {
-        final CallerIdentity caller = getCallerIdentity();
-        if (isDeviceOwner(caller) || isProfileOwner(caller)) {
-            return;
-        }
-        Preconditions.checkState(isSystemUid(caller),
-                "Only profile owner, device owner and system may call this method.");
-    }
-
-    private void enforceProfileOwnerOrFullCrossUsersPermission(CallerIdentity caller,
-            int userId) {
-        if ((userId == caller.getUserId()) && (isProfileOwner(caller) || isDeviceOwner(caller))) {
-            // Device Owner/Profile Owner may access the user it runs on.
-            return;
-        }
-        Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId));
-    }
-
     private boolean canUserUseLockTaskLocked(int userId) {
         if (isUserAffiliatedWithDeviceLocked(userId)) {
             return true;
@@ -12458,7 +12433,8 @@
         if (!mHasFeature) {
             return null;
         }
-        enforceDeviceOwnerOrManageUsers();
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
         synchronized (getLockObject()) {
             final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked();
             return deviceOwnerAdmin == null ? null : deviceOwnerAdmin.organizationName;
@@ -13605,19 +13581,22 @@
 
     @Override
     public long getLastSecurityLogRetrievalTime() {
-        enforceDeviceOwnerOrManageUsers();
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
         return getUserData(UserHandle.USER_SYSTEM).mLastSecurityLogRetrievalTime;
      }
 
     @Override
     public long getLastBugReportRequestTime() {
-        enforceDeviceOwnerOrManageUsers();
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
         return getUserData(UserHandle.USER_SYSTEM).mLastBugReportRequestTime;
      }
 
     @Override
     public long getLastNetworkLogRetrievalTime() {
-        enforceDeviceOwnerOrManageUsers();
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
         return getUserData(UserHandle.USER_SYSTEM).mLastNetworkLogsRetrievalTime;
     }
 
@@ -13721,15 +13700,21 @@
 
     @Override
     public boolean isCurrentInputMethodSetByOwner() {
-        enforceProfileOwnerOrSystemUser();
-        return getUserData(mInjector.userHandleGetCallingUserId()).mCurrentInputMethodSet;
+        final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+                || isProfileOwner(caller) || isSystemUid(caller),
+                "Only profile owner, device owner and system may call this method.");
+        return getUserData(caller.getUserId()).mCurrentInputMethodSet;
     }
 
     @Override
     public StringParceledListSlice getOwnerInstalledCaCerts(@NonNull UserHandle user) {
         final int userId = user.getIdentifier();
         final CallerIdentity caller = getCallerIdentity();
-        enforceProfileOwnerOrFullCrossUsersPermission(caller, userId);
+        Preconditions.checkCallAuthorization((userId == caller.getUserId())
+                || isProfileOwner(caller) || isDeviceOwner(caller)
+                || hasFullCrossUsersPermission(caller, userId));
+
         synchronized (getLockObject()) {
             return new StringParceledListSlice(
                     new ArrayList<>(getUserData(userId).mOwnerInstalledCaCerts));
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 03edc58..267c9b7 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1266,6 +1266,12 @@
             inputManager = new InputManagerService(context);
             t.traceEnd();
 
+            if (!disableCameraService) {
+                t.traceBegin("StartCameraServiceProxy");
+                mSystemServiceManager.startService(CameraServiceProxy.class);
+                t.traceEnd();
+            }
+
             t.traceBegin("StartWindowManagerService");
             // WMS needs sensor service ready
             ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
@@ -2200,12 +2206,6 @@
             t.traceEnd();
         }
 
-        if (!disableCameraService) {
-            t.traceBegin("StartCameraServiceProxy");
-            mSystemServiceManager.startService(CameraServiceProxy.class);
-            t.traceEnd();
-        }
-
         if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED)) {
             t.traceBegin("StartIoTSystemService");
             mSystemServiceManager.startService(IOT_SERVICE_CLASS);
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/AppSearchImplTest.java
rename to services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index 081bfb5..0d0ac6d 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.appsearch.external.localbackend;
+package com.android.server.appsearch.external.localstorage;
 
 import static com.google.common.truth.Truth.assertThat;
 
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java
similarity index 86%
rename from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverterTest.java
rename to services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java
index a95290d..85d4f01 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverterTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.appsearch.external.localbackend.converter;
+package com.android.server.appsearch.external.localstorage.converter;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -53,13 +53,13 @@
                         .setScore(1)
                         .setTtlMillis(1L)
                         .setNamespace("namespace")
-                        .setProperty("longKey1", 1L)
-                        .setProperty("doubleKey1", 1.0)
-                        .setProperty("booleanKey1", true)
-                        .setProperty("stringKey1", "test-value1")
-                        .setProperty("byteKey1", BYTE_ARRAY_1, BYTE_ARRAY_2)
-                        .setProperty("documentKey1", DOCUMENT_PROPERTIES_1)
-                        .setProperty(GenericDocument.PROPERTIES_FIELD, DOCUMENT_PROPERTIES_2)
+                        .setPropertyLong("longKey1", 1L)
+                        .setPropertyDouble("doubleKey1", 1.0)
+                        .setPropertyBoolean("booleanKey1", true)
+                        .setPropertyString("stringKey1", "test-value1")
+                        .setPropertyBytes("byteKey1", BYTE_ARRAY_1, BYTE_ARRAY_2)
+                        .setPropertyDocument("documentKey1", DOCUMENT_PROPERTIES_1)
+                        .setPropertyDocument("documentKey2", DOCUMENT_PROPERTIES_2)
                         .build();
 
         // Create the Document proto. Need to sort the property order by key.
@@ -87,8 +87,8 @@
                 PropertyProto.newBuilder().setName("documentKey1")
                         .addDocumentValues(
                                 GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_1)));
-        propertyProtoMap.put(GenericDocument.PROPERTIES_FIELD,
-                PropertyProto.newBuilder().setName(GenericDocument.PROPERTIES_FIELD)
+        propertyProtoMap.put("documentKey2",
+                PropertyProto.newBuilder().setName("documentKey2")
                         .addDocumentValues(
                                 GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_2)));
         List<String> sortedKey = new ArrayList<>(propertyProtoMap.keySet());
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
similarity index 96%
rename from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverterTest.java
rename to services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
index 8b2fd1c..7336c3c 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverterTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.appsearch.external.localbackend.converter;
+package com.android.server.appsearch.external.localstorage.converter;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -50,7 +50,6 @@
                 .addProperties(PropertyConfigProto.newBuilder()
                         .setPropertyName("subject")
                         .setDataType(PropertyConfigProto.DataType.Code.STRING)
-                        .setSchemaType("")
                         .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
                         .setIndexingConfig(
                                 com.android.server.appsearch.proto.IndexingConfig.newBuilder()
@@ -60,7 +59,6 @@
                 ).addProperties(PropertyConfigProto.newBuilder()
                         .setPropertyName("body")
                         .setDataType(PropertyConfigProto.DataType.Code.STRING)
-                        .setSchemaType("")
                         .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
                         .setIndexingConfig(
                                 com.android.server.appsearch.proto.IndexingConfig.newBuilder()
@@ -94,7 +92,6 @@
                 .addProperties(PropertyConfigProto.newBuilder()
                         .setPropertyName("artist")
                         .setDataType(PropertyConfigProto.DataType.Code.STRING)
-                        .setSchemaType("")
                         .setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED)
                         .setIndexingConfig(
                                 com.android.server.appsearch.proto.IndexingConfig.newBuilder()
@@ -104,7 +101,6 @@
                 ).addProperties(PropertyConfigProto.newBuilder()
                         .setPropertyName("pubDate")
                         .setDataType(PropertyConfigProto.DataType.Code.INT64)
-                        .setSchemaType("")
                         .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
                         .setIndexingConfig(
                                 com.android.server.appsearch.proto.IndexingConfig.newBuilder()
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SnippetTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SnippetTest.java
rename to services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
index e9357aa..d5762a1 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SnippetTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.appsearch.external.localbackend.converter;
+package com.android.server.appsearch.external.localstorage.converter;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -123,7 +123,7 @@
 
         for (SearchResultProto.ResultProto proto : searchResultProto.getResultsList()) {
             SearchResult result = SearchResultToProtoConverter.convertSearchResult(proto);
-            assertThat(result.getMatches()).isEqualTo(null);
+            assertThat(result.getMatches()).isEmpty();
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java
index 7a0d894..b73a783 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java
@@ -46,6 +46,10 @@
     private Face10 mFace10;
     private IBinder mBinder;
 
+    private static void waitForIdle() {
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -59,11 +63,8 @@
 
     @Test
     public void scheduleRevokeChallenge_doesNotCrash() {
-        mFace10.scheduleRevokeChallenge(mBinder, TAG);
+        mFace10.scheduleRevokeChallenge(0 /* sensorId */, 0 /* userId */, mBinder, TAG,
+                0 /* challenge */);
         waitForIdle();
     }
-
-    private static void waitForIdle() {
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java
index be05245..9660d6b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java
@@ -15,33 +15,33 @@
  */
 package com.android.server.devicepolicy;
 
-import android.test.AndroidTestCase;
+import static com.google.common.truth.Truth.assertThat;
+
 import android.test.suitebuilder.annotation.SmallTest;
 
+import org.junit.Test;
+
 /**
  * Test for {@link DevicePolicyConstants}.
  *
- m FrameworksServicesTests &&
- adb install \
- -r ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
- adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyConstantsTest \
- -w com.android.frameworks.servicestests
-
-
- -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
+ * <p>Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyConstantsTest}
  */
 @SmallTest
-public class DevicePolicyConstantsTest extends AndroidTestCase {
+public class DevicePolicyConstantsTest {
     private static final String TAG = "DevicePolicyConstantsTest";
 
+    @Test
     public void testDefaultValues() throws Exception {
         final DevicePolicyConstants constants = DevicePolicyConstants.loadFromString("");
 
-        assertEquals(1 * 60 * 60, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC);
-        assertEquals(24 * 60 * 60, constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC);
-        assertEquals(2.0, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE);
+        assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC).isEqualTo(1 * 60 * 60);
+        assertThat(constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC).isEqualTo(24 * 60 * 60);
+        assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE).isWithin(1.0e-10).of(2.0);
     }
 
+    @Test
     public void testCustomValues() throws Exception {
         final DevicePolicyConstants constants = DevicePolicyConstants.loadFromString(
                 "das_died_service_reconnect_backoff_sec=10,"
@@ -49,11 +49,13 @@
                 + "das_died_service_reconnect_max_backoff_sec=15"
         );
 
-        assertEquals(10, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC);
-        assertEquals(15, constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC);
-        assertEquals(1.25, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE);
+        assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC).isEqualTo(10);
+        assertThat(constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC).isEqualTo(15);
+        assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE).isWithin(1.0e-10)
+                .of(1.25);
     }
 
+    @Test
     public void testMinMax() throws Exception {
         final DevicePolicyConstants constants = DevicePolicyConstants.loadFromString(
                 "das_died_service_reconnect_backoff_sec=3,"
@@ -61,8 +63,8 @@
                         + "das_died_service_reconnect_max_backoff_sec=1"
         );
 
-        assertEquals(5, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC);
-        assertEquals(5, constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC);
-        assertEquals(1.0, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE);
+        assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC).isEqualTo(5);
+        assertThat(constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC).isEqualTo(5);
+        assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE).isWithin(1.0e-10).of(1.0);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyEventLoggerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyEventLoggerTest.java
index b24bca8..350b390 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyEventLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyEventLoggerTest.java
@@ -46,8 +46,8 @@
                 .setTimePeriod(1234L);
         assertThat(eventLogger.getEventId()).isEqualTo(5);
         assertThat(eventLogger.getBoolean()).isTrue();
-        assertThat(eventLogger.getStringArray())
-                .isEqualTo(new String[] {"string1", "string2", "string3"});
+        assertThat(eventLogger.getStringArray()).asList()
+            .containsExactly("string1", "string2", "string3");
         assertThat(eventLogger.getAdminPackageName()).isEqualTo("com.test.package");
         assertThat(eventLogger.getInt()).isEqualTo(4321);
         assertThat(eventLogger.getTimePeriod()).isEqualTo(1234L);
@@ -57,23 +57,22 @@
     public void testStrings() {
         assertThat(DevicePolicyEventLogger
                 .createEvent(0)
-                .setStrings("string1", "string2", "string3").getStringArray())
-                .isEqualTo(new String[] {"string1", "string2", "string3"});
+                .setStrings("string1", "string2", "string3").getStringArray()).asList()
+                        .containsExactly("string1", "string2", "string3").inOrder();
 
         assertThat(DevicePolicyEventLogger
                 .createEvent(0)
                 .setStrings("string1", new String[] {"string2", "string3"}).getStringArray())
-                .isEqualTo(new String[] {"string1", "string2", "string3"});
+                        .asList().containsExactly("string1", "string2", "string3").inOrder();
 
         assertThat(DevicePolicyEventLogger
                 .createEvent(0)
                 .setStrings("string1", "string2", new String[] {"string3"}).getStringArray())
-                .isEqualTo(new String[] {"string1", "string2", "string3"});
-
+                        .asList().containsExactly("string1", "string2", "string3").inOrder();
         assertThat(DevicePolicyEventLogger
                 .createEvent(0)
-                .setStrings((String) null).getStringArray())
-                .isEqualTo(new String[] {null});
+                .setStrings((String) null).getStringArray()).asList()
+                        .containsExactly((String) null);
 
         assertThat(DevicePolicyEventLogger
                 .createEvent(0)
@@ -106,8 +105,8 @@
                 .createEvent(0);
         assertThat(eventLogger.getEventId()).isEqualTo(0);
         assertThat(eventLogger.getBoolean()).isFalse();
-        assertThat(eventLogger.getStringArray()).isEqualTo(null);
-        assertThat(eventLogger.getAdminPackageName()).isEqualTo(null);
+        assertThat(eventLogger.getStringArray()).isNull();
+        assertThat(eventLogger.getAdminPackageName()).isNull();
         assertThat(eventLogger.getInt()).isEqualTo(0);
         assertThat(eventLogger.getTimePeriod()).isEqualTo(0L);
     }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
index 3167820..fa3f45c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
@@ -20,7 +20,9 @@
 import static com.android.server.devicepolicy.DpmTestUtils.writeInputStreamToFile;
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 
-import static org.junit.Assert.assertArrayEquals;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
@@ -43,17 +45,23 @@
 import android.provider.Settings;
 
 import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.servicestests.R;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.File;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
 @Presubmit
+@RunWith(AndroidJUnit4.class)
 public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
 
     private static final String USER_TYPE_EMPTY = "";
@@ -63,9 +71,8 @@
 
     private DpmMockContext mContext;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws Exception {
 
         mContext = getContext();
 
@@ -77,6 +84,7 @@
                 .thenReturn(true);
     }
 
+    @Test
     public void testMigration() throws Exception {
         final File user10dir = getServices().addUser(10, 0, USER_TYPE_EMPTY);
         final File user11dir = getServices().addUser(11, 0,
@@ -160,19 +168,19 @@
             mContext.binder.restoreCallingIdentity(ident);
         }
 
-        assertTrue(dpms.mOwners.hasDeviceOwner());
-        assertFalse(dpms.mOwners.hasProfileOwner(USER_SYSTEM));
-        assertTrue(dpms.mOwners.hasProfileOwner(10));
-        assertTrue(dpms.mOwners.hasProfileOwner(11));
-        assertFalse(dpms.mOwners.hasProfileOwner(12));
+        assertThat(dpms.mOwners.hasDeviceOwner()).isTrue();
+        assertThat(dpms.mOwners.hasProfileOwner(USER_SYSTEM)).isFalse();
+        assertThat(dpms.mOwners.hasProfileOwner(10)).isTrue();
+        assertThat(dpms.mOwners.hasProfileOwner(11)).isTrue();
+        assertThat(dpms.mOwners.hasProfileOwner(12)).isFalse();
 
         // Now all information should be migrated.
-        assertFalse(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration());
-        assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(
-                USER_SYSTEM));
-        assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-        assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-        assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(12));
+        assertThat(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+        assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(USER_SYSTEM))
+            .isFalse();
+        assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+        assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+        assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(12)).isFalse();
 
         // Check the new base restrictions.
         DpmTestUtils.assertRestrictions(
@@ -221,6 +229,7 @@
                 dpms.getProfileOwnerAdminLocked(11).ensureUserRestrictions());
     }
 
+    @Test
     public void testMigration2_profileOwnerOnUser0() throws Exception {
         setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_SYSTEM_USER_UID);
 
@@ -271,13 +280,13 @@
         } finally {
             mContext.binder.restoreCallingIdentity(ident);
         }
-        assertFalse(dpms.mOwners.hasDeviceOwner());
-        assertTrue(dpms.mOwners.hasProfileOwner(USER_SYSTEM));
+        assertThat(dpms.mOwners.hasDeviceOwner()).isFalse();
+        assertThat(dpms.mOwners.hasProfileOwner(USER_SYSTEM)).isTrue();
 
         // Now all information should be migrated.
-        assertFalse(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration());
-        assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(
-                USER_SYSTEM));
+        assertThat(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+        assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(USER_SYSTEM))
+            .isFalse();
 
         // Check the new base restrictions.
         DpmTestUtils.assertRestrictions(
@@ -297,6 +306,7 @@
     }
 
     // Test setting default restrictions for managed profile.
+    @Test
     public void testMigration3_managedProfileOwner() throws Exception {
         // Create a managed profile user.
         final File user10dir = getServices().addUser(10, 0,
@@ -339,8 +349,8 @@
             mContext.binder.restoreCallingIdentity(ident);
         }
 
-        assertFalse(dpms.mOwners.hasDeviceOwner());
-        assertTrue(dpms.mOwners.hasProfileOwner(10));
+        assertThat(dpms.mOwners.hasDeviceOwner()).isFalse();
+        assertThat(dpms.mOwners.hasProfileOwner(10)).isTrue();
 
         // Check that default restrictions were applied.
         DpmTestUtils.assertRestrictions(
@@ -352,11 +362,12 @@
 
         final Set<String> alreadySet =
                 dpms.getProfileOwnerAdminLocked(10).defaultEnabledRestrictionsAlreadySet;
-        assertEquals(alreadySet.size(), 1);
-        assertTrue(alreadySet.contains(UserManager.DISALLOW_BLUETOOTH_SHARING));
+        assertThat(alreadySet).hasSize(1);
+        assertThat(alreadySet.contains(UserManager.DISALLOW_BLUETOOTH_SHARING)).isTrue();
     }
 
     @SmallTest
+    @Test
     public void testCompMigrationUnAffiliated_skipped() throws Exception {
         prepareAdmin1AsDo();
         prepareAdminAnotherPackageAsPo(COPE_PROFILE_USER_ID);
@@ -364,10 +375,11 @@
         final DevicePolicyManagerServiceTestable dpms = bootDpmsUp();
 
         // DO should still be DO since no migration should happen.
-        assertTrue(dpms.mOwners.hasDeviceOwner());
+        assertThat(dpms.mOwners.hasDeviceOwner()).isTrue();
     }
 
     @SmallTest
+    @Test
     public void testCompMigrationAffiliated() throws Exception {
         prepareAdmin1AsDo();
         prepareAdmin1AsPo(COPE_PROFILE_USER_ID, Build.VERSION_CODES.R);
@@ -378,48 +390,54 @@
         final DevicePolicyManagerServiceTestable dpms = bootDpmsUp();
 
         // DO should cease to be DO.
-        assertFalse(dpms.mOwners.hasDeviceOwner());
+        assertThat(dpms.mOwners.hasDeviceOwner()).isFalse();
 
         final DpmMockContext poContext = new DpmMockContext(getServices(), mRealTestContext);
         poContext.binder.callingUid = UserHandle.getUid(COPE_PROFILE_USER_ID, COPE_ADMIN1_APP_ID);
 
         runAsCaller(poContext, dpms, dpm -> {
-            assertEquals("Password history policy wasn't migrated to PO parent instance",
-                    33, dpm.getParentProfileInstance(admin1).getPasswordHistoryLength(admin1));
-            assertEquals("Password history policy was put into non-parent PO instance",
-                    0, dpm.getPasswordHistoryLength(admin1));
-            assertTrue("Screen capture restriction wasn't migrated to PO parent instance",
-                    dpm.getParentProfileInstance(admin1).getScreenCaptureDisabled(admin1));
+            assertWithMessage("Password history policy wasn't migrated to PO parent instance")
+                    .that(dpm.getParentProfileInstance(admin1).getPasswordHistoryLength(admin1))
+                    .isEqualTo(33);
+            assertWithMessage("Password history policy was put into non-parent PO instance")
+                    .that(dpm.getPasswordHistoryLength(admin1)).isEqualTo(0);
+            assertWithMessage("Screen capture restriction wasn't migrated to PO parent instance")
+                    .that(dpm.getParentProfileInstance(admin1).getScreenCaptureDisabled(admin1))
+                    .isTrue();
 
-            assertArrayEquals("Accounts with management disabled weren't migrated to PO parent",
-                    new String[] {"com.google-primary"},
-                    dpm.getParentProfileInstance(admin1).getAccountTypesWithManagementDisabled());
-            assertArrayEquals("Accounts with management disabled for profile were lost",
-                    new String[] {"com.google-profile"},
-                    dpm.getAccountTypesWithManagementDisabled());
+            assertWithMessage("Accounts with management disabled weren't migrated to PO parent")
+                    .that(dpm.getParentProfileInstance(admin1)
+                            .getAccountTypesWithManagementDisabled()).asList()
+                    .containsExactly("com.google-primary");
 
-            assertTrue("User restriction wasn't migrated to PO parent instance",
-                    dpm.getParentProfileInstance(admin1).getUserRestrictions(admin1)
-                            .containsKey(UserManager.DISALLOW_BLUETOOTH));
-            assertFalse("User restriction was put into non-parent PO instance",
-                    dpm.getUserRestrictions(admin1).containsKey(UserManager.DISALLOW_BLUETOOTH));
+            assertWithMessage("Accounts with management disabled for profile were lost")
+                    .that(dpm.getAccountTypesWithManagementDisabled()).asList()
+                    .containsExactly("com.google-profile");
 
-            assertTrue("User restriction wasn't migrated to PO parent instance",
-                    dpms.getProfileOwnerAdminLocked(COPE_PROFILE_USER_ID)
-                            .getParentActiveAdmin()
-                            .getEffectiveRestrictions()
-                            .containsKey(UserManager.DISALLOW_CONFIG_DATE_TIME));
-            assertFalse("User restriction was put into non-parent PO instance",
-                    dpms.getProfileOwnerAdminLocked(COPE_PROFILE_USER_ID)
-                            .getEffectiveRestrictions()
-                            .containsKey(UserManager.DISALLOW_CONFIG_DATE_TIME));
-            assertEquals("Personal apps suspension wasn't migrated",
-                    DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED,
-                    dpm.getPersonalAppsSuspendedReasons(admin1));
+            assertWithMessage("User restriction wasn't migrated to PO parent instance")
+                    .that(dpm.getParentProfileInstance(admin1).getUserRestrictions(admin1).keySet())
+                    .contains(UserManager.DISALLOW_BLUETOOTH);
+
+            assertWithMessage("User restriction was put into non-parent PO instance").that(
+                    dpm.getUserRestrictions(admin1).keySet())
+                    .doesNotContain(UserManager.DISALLOW_BLUETOOTH);
+
+            assertWithMessage("User restriction wasn't migrated to PO parent instance")
+                    .that(dpms.getProfileOwnerAdminLocked(COPE_PROFILE_USER_ID)
+                            .getParentActiveAdmin().getEffectiveRestrictions().keySet())
+                    .contains(UserManager.DISALLOW_CONFIG_DATE_TIME);
+            assertWithMessage("User restriction was put into non-parent PO instance")
+                    .that(dpms.getProfileOwnerAdminLocked(COPE_PROFILE_USER_ID)
+                            .getEffectiveRestrictions().keySet())
+                    .doesNotContain(UserManager.DISALLOW_CONFIG_DATE_TIME);
+            assertWithMessage("Personal apps suspension wasn't migrated")
+                    .that(dpm.getPersonalAppsSuspendedReasons(admin1))
+                    .isEqualTo(DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED);
         });
     }
 
     @SmallTest
+    @Test
     public void testCompMigration_keepSuspendedAppsWhenDpcIsRPlus() throws Exception {
         prepareAdmin1AsDo();
         prepareAdmin1AsPo(COPE_PROFILE_USER_ID, Build.VERSION_CODES.R);
@@ -445,13 +463,14 @@
         poContext.binder.callingUid = UserHandle.getUid(COPE_PROFILE_USER_ID, COPE_ADMIN1_APP_ID);
 
         runAsCaller(poContext, dpms, dpm -> {
-            assertEquals("Personal apps suspension wasn't migrated",
-                    DevicePolicyManager.PERSONAL_APPS_SUSPENDED_EXPLICITLY,
-                    dpm.getPersonalAppsSuspendedReasons(admin1));
+            assertWithMessage("Personal apps suspension wasn't migrated")
+                    .that(dpm.getPersonalAppsSuspendedReasons(admin1))
+                    .isEqualTo(DevicePolicyManager.PERSONAL_APPS_SUSPENDED_EXPLICITLY);
         });
     }
 
     @SmallTest
+    @Test
     public void testCompMigration_unsuspendAppsWhenDpcNotRPlus() throws Exception {
         prepareAdmin1AsDo();
         prepareAdmin1AsPo(COPE_PROFILE_USER_ID, Build.VERSION_CODES.Q);
@@ -470,9 +489,9 @@
         poContext.binder.callingUid = UserHandle.getUid(COPE_PROFILE_USER_ID, COPE_ADMIN1_APP_ID);
 
         runAsCaller(poContext, dpms, dpm -> {
-            assertEquals("Personal apps weren't unsuspended",
-                    DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED,
-                    dpm.getPersonalAppsSuspendedReasons(admin1));
+            assertWithMessage("Personal apps weren't unsuspended")
+                    .that(dpm.getPersonalAppsSuspendedReasons(admin1))
+                    .isEqualTo(DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED);
         });
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index c4f7b95..8d7bc16 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -39,7 +39,9 @@
 import static com.android.server.testutils.TestUtils.assertExpectException;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
@@ -89,13 +91,14 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.FlakyTest;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 import android.security.KeyChain;
 import android.security.keystore.AttestationUtils;
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
-import android.test.MoreAsserts;
+import android.test.MoreAsserts; // TODO(b/171932723): replace by Truth
 import android.util.ArraySet;
 import android.util.Pair;
 
@@ -111,6 +114,9 @@
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 import org.mockito.Mockito;
 import org.mockito.internal.util.collections.Sets;
 import org.mockito.stubbing.Answer;
@@ -127,17 +133,11 @@
 
 /**
  * Tests for DevicePolicyManager( and DevicePolicyManagerService).
- * You can run them via:
- m FrameworksServicesTests &&
- adb install \
-   -r ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
- adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyManagerTest \
-   -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
-
- (mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
  *
- * , or:
- * runtest -c com.android.server.devicepolicy.DevicePolicyManagerTest frameworks-services
+ * <p>Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest}
+ *
  */
 @SmallTest
 @Presubmit
@@ -205,9 +205,8 @@
     private static final String PROFILE_OFF_SUSPENSION_TEXT = "suspension_text";
     private static final String PROFILE_OFF_SUSPENSION_SOON_TEXT = "suspension_tomorrow_text";
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws Exception {
 
         mContext = getContext();
         mServiceContext = mContext;
@@ -251,11 +250,10 @@
         return dpms.mTransferOwnershipMetadataManager;
     }
 
-    @Override
-    protected void tearDown() throws Exception {
+    @After
+    public void tearDown() throws Exception {
         flushTasks(dpms);
         getMockTransferMetadataManager().deleteMetadataFile();
-        super.tearDown();
     }
 
     private void initializeDpms() {
@@ -336,14 +334,15 @@
             // PO needs to be a DA.
             dpm.setActiveAdmin(admin, /*replace=*/ false);
             // Fire!
-            assertTrue(dpm.setProfileOwner(admin, "owner-name", CALLER_USER_HANDLE));
+            assertThat(dpm.setProfileOwner(admin, "owner-name", CALLER_USER_HANDLE)).isTrue();
             // Check
-            assertEquals(admin, dpm.getProfileOwnerAsUser(CALLER_USER_HANDLE));
+            assertThat(dpm.getProfileOwnerAsUser(CALLER_USER_HANDLE)).isEqualTo(admin);
         });
 
         mServiceContext.binder.restoreCallingIdentity(ident);
     }
 
+    @Test
     public void testHasNoFeature() throws Exception {
         when(getServices().packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
                 .thenReturn(false);
@@ -352,9 +351,10 @@
         new DevicePolicyManagerServiceTestable(getServices(), mContext);
 
         // If the device has no DPMS feature, it shouldn't register the local service.
-        assertNull(LocalServices.getService(DevicePolicyManagerInternal.class));
+        assertThat(LocalServices.getService(DevicePolicyManagerInternal.class)).isNull();
     }
 
+    @Test
     public void testLoadAdminData() throws Exception {
         // Device owner in SYSTEM_USER
         setDeviceOwner();
@@ -365,7 +365,7 @@
         final int ANOTHER_UID = UserHandle.getUid(CALLER_USER_HANDLE, 1306);
         setUpPackageManagerForFakeAdmin(adminAnotherPackage, ANOTHER_UID, admin2);
         dpm.setActiveAdmin(adminAnotherPackage, /* replace =*/ false, CALLER_USER_HANDLE);
-        assertTrue(dpm.isAdminActiveAsUser(adminAnotherPackage, CALLER_USER_HANDLE));
+        assertThat(dpm.isAdminActiveAsUser(adminAnotherPackage, CALLER_USER_HANDLE)).isTrue();
 
         initializeDpms();
 
@@ -381,6 +381,7 @@
         verify(getServices().networkPolicyManagerInternal).onAdminDataAvailable();
     }
 
+    @Test
     public void testLoadAdminData_noAdmins() throws Exception {
         final int ANOTHER_USER_ID = 15;
         getServices().addUser(ANOTHER_USER_ID, 0, "");
@@ -399,6 +400,7 @@
     /**
      * Caller doesn't have proper permissions.
      */
+    @Test
     public void testSetActiveAdmin_SecurityException() {
         // 1. Failure cases.
 
@@ -422,6 +424,7 @@
      * {@link DevicePolicyManager#getActiveAdmins}
      * {@link DevicePolicyManager#getActiveAdminsAsUser}
      */
+    @Test
     public void testSetActiveAdmin() throws Exception {
         // 1. Make sure the caller has proper permissions.
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -456,9 +459,9 @@
         // TODO Verify other calls too.
 
         // Make sure it's active admin1.
-        assertTrue(dpm.isAdminActive(admin1));
-        assertFalse(dpm.isAdminActive(admin2));
-        assertFalse(dpm.isAdminActive(admin3));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
+        assertThat(dpm.isAdminActive(admin2)).isFalse();
+        assertThat(dpm.isAdminActive(admin3)).isFalse();
 
         // But not admin1 for a different user.
 
@@ -466,8 +469,8 @@
         // (Because we're checking a different user's status from CALLER_USER_HANDLE.)
         mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
 
-        assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE + 1));
-        assertFalse(dpm.isAdminActiveAsUser(admin2, CALLER_USER_HANDLE + 1));
+        assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE + 1)).isFalse();
+        assertThat(dpm.isAdminActiveAsUser(admin2, CALLER_USER_HANDLE + 1)).isFalse();
 
         mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
 
@@ -479,9 +482,9 @@
         dpm.setActiveAdmin(admin2, /* replace =*/ false);
 
         // Now we have two admins.
-        assertTrue(dpm.isAdminActive(admin1));
-        assertTrue(dpm.isAdminActive(admin2));
-        assertFalse(dpm.isAdminActive(admin3));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
+        assertThat(dpm.isAdminActive(admin2)).isTrue();
+        assertThat(dpm.isAdminActive(admin3)).isFalse();
 
         // Admin2 was already enabled, so setApplicationEnabledSetting() shouldn't have called
         // again.  (times(1) because it was previously called for admin1)
@@ -508,9 +511,9 @@
 
         // 6. Test getActiveAdmins()
         List<ComponentName> admins = dpm.getActiveAdmins();
-        assertEquals(2, admins.size());
-        assertEquals(admin1, admins.get(0));
-        assertEquals(admin2, admins.get(1));
+        assertThat(admins.size()).isEqualTo(2);
+        assertThat(admins.get(0)).isEqualTo(admin1);
+        assertThat(admins.get(1)).isEqualTo(admin2);
 
         // There shouldn't be any callback to UsageStatsManagerInternal when the admin is being
         // replaced
@@ -519,12 +522,13 @@
         // Another user has no admins.
         mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
 
-        assertEquals(0, DpmTestUtils.getListSizeAllowingNull(
-                dpm.getActiveAdminsAsUser(CALLER_USER_HANDLE + 1)));
+        assertThat(DpmTestUtils.getListSizeAllowingNull(
+        dpm.getActiveAdminsAsUser(CALLER_USER_HANDLE + 1))).isEqualTo(0);
 
         mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
     }
 
+    @Test
     public void testSetActiveAdmin_multiUsers() throws Exception {
 
         final int ANOTHER_USER_ID = 100;
@@ -544,12 +548,12 @@
 
 
         mMockContext.binder.callingUid = DpmMockContext.CALLER_UID;
-        assertTrue(dpm.isAdminActive(admin1));
-        assertFalse(dpm.isAdminActive(admin2));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
+        assertThat(dpm.isAdminActive(admin2)).isFalse();
 
         mMockContext.binder.callingUid = ANOTHER_ADMIN_UID;
-        assertFalse(dpm.isAdminActive(admin1));
-        assertTrue(dpm.isAdminActive(admin2));
+        assertThat(dpm.isAdminActive(admin1)).isFalse();
+        assertThat(dpm.isAdminActive(admin2)).isTrue();
     }
 
     /**
@@ -557,12 +561,13 @@
      * {@link DevicePolicyManager#setActiveAdmin}
      * with replace=false
      */
+    @Test
     public void testSetActiveAdmin_twiceWithoutReplace() throws Exception {
         // 1. Make sure the caller has proper permissions.
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
 
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
-        assertTrue(dpm.isAdminActive(admin1));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
 
         // Add the same admin1 again without replace, which should throw.
         assertExpectException(IllegalArgumentException.class, /* messageRegex= */ null,
@@ -574,6 +579,7 @@
      * {@link DevicePolicyManager#setActiveAdmin} when the admin isn't protected with
      * BIND_DEVICE_ADMIN.
      */
+    @Test
     public void testSetActiveAdmin_permissionCheck() throws Exception {
         // 1. Make sure the caller has proper permissions.
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -581,13 +587,13 @@
         assertExpectException(IllegalArgumentException.class,
                 /* messageRegex= */ permission.BIND_DEVICE_ADMIN,
                 () -> dpm.setActiveAdmin(adminNoPerm, /* replace =*/ false));
-        assertFalse(dpm.isAdminActive(adminNoPerm));
+        assertThat(dpm.isAdminActive(adminNoPerm)).isFalse();
 
         // Change the target API level to MNC.  Now it can be set as DA.
         setUpPackageManagerForAdmin(adminNoPerm, DpmMockContext.CALLER_UID, null,
                 VERSION_CODES.M);
         dpm.setActiveAdmin(adminNoPerm, /* replace =*/ false);
-        assertTrue(dpm.isAdminActive(adminNoPerm));
+        assertThat(dpm.isAdminActive(adminNoPerm)).isTrue();
 
         // TODO Test the "load from the file" case where DA will still be loaded even without
         // BIND_DEVICE_ADMIN and target API is N.
@@ -597,6 +603,7 @@
      * Test for:
      * {@link DevicePolicyManager#removeActiveAdmin}
      */
+    @Test
     public void testRemoveActiveAdmin_SecurityException() {
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
 
@@ -604,9 +611,9 @@
 
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
 
-        assertTrue(dpm.isAdminActive(admin1));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
 
-        assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
 
         // Directly call the DPMS method with a different userid, which should fail.
         assertExpectException(SecurityException.class, /* messageRegex =*/ null,
@@ -627,6 +634,7 @@
      * {@link DevicePolicyManager#removeActiveAdmin} should fail with the user is not unlocked
      * (because we can't send the remove broadcast).
      */
+    @Test
     public void testRemoveActiveAdmin_userNotRunningOrLocked() {
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
 
@@ -636,9 +644,9 @@
 
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
 
-        assertTrue(dpm.isAdminActive(admin1));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
 
-        assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
 
         // 1. User not unlocked.
         setUserUnlocked(CALLER_USER_HANDLE, false);
@@ -646,7 +654,7 @@
                 /* messageRegex= */ "User must be running and unlocked",
                 () -> dpm.removeActiveAdmin(admin1));
 
-        assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
         verify(getServices().usageStatsManagerInternal, times(0)).setActiveAdminApps(
                 null, CALLER_USER_HANDLE);
 
@@ -654,7 +662,7 @@
         setUserUnlocked(CALLER_USER_HANDLE, true);
 
         dpm.removeActiveAdmin(admin1);
-        assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
         verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
                 null, CALLER_USER_HANDLE);
     }
@@ -663,6 +671,7 @@
      * Test for:
      * {@link DevicePolicyManager#removeActiveAdmin}
      */
+    @Test
     public void testRemoveActiveAdmin_fromDifferentUserWithINTERACT_ACROSS_USERS_FULL() {
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
 
@@ -670,8 +679,8 @@
 
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
 
-        assertTrue(dpm.isAdminActive(admin1));
-        assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
+        assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
 
         // Different user, but should work, because caller has proper permissions.
         mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
@@ -680,7 +689,7 @@
         mContext.binder.callingUid = 1234567;
 
         dpms.removeActiveAdmin(admin1, CALLER_USER_HANDLE);
-        assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
         verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
                 null, CALLER_USER_HANDLE);
 
@@ -691,6 +700,7 @@
      * Test for:
      * {@link DevicePolicyManager#removeActiveAdmin}
      */
+    @Test
     public void testRemoveActiveAdmin_sameUserNoMANAGE_DEVICE_ADMINS() {
         // Need MANAGE_DEVICE_ADMINS for setActiveAdmin.  We'll remove it later.
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -699,8 +709,8 @@
 
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
 
-        assertTrue(dpm.isAdminActive(admin1));
-        assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
+        assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
 
         // Broadcast from saveSettingsLocked().
         verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
@@ -725,7 +735,7 @@
                 isNull(String.class),
                 isNull(Bundle.class));
 
-        assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
         verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
                 null, CALLER_USER_HANDLE);
 
@@ -738,6 +748,7 @@
         // TODO Check other internal calls.
     }
 
+    @Test
     public void testRemoveActiveAdmin_multipleAdminsInUser() {
         // Need MANAGE_DEVICE_ADMINS for setActiveAdmin.  We'll remove it later.
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -745,14 +756,14 @@
         // Add admin1.
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
 
-        assertTrue(dpm.isAdminActive(admin1));
-        assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
+        assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
 
         // Add admin2.
         dpm.setActiveAdmin(admin2, /* replace =*/ false);
 
-        assertTrue(dpm.isAdminActive(admin2));
-        assertFalse(dpm.isRemovingAdmin(admin2, CALLER_USER_HANDLE));
+        assertThat(dpm.isAdminActive(admin2)).isTrue();
+        assertThat(dpm.isRemovingAdmin(admin2, CALLER_USER_HANDLE)).isFalse();
 
         // Broadcast from saveSettingsLocked().
         verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
@@ -777,7 +788,7 @@
                 isNull(String.class),
                 isNull(Bundle.class));
 
-        assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
         verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
                 MockUtils.checkApps(admin2.getPackageName()),
                 eq(CALLER_USER_HANDLE));
@@ -793,6 +804,7 @@
      * Test for:
      * {@link DevicePolicyManager#forceRemoveActiveAdmin(ComponentName, int)}
      */
+    @Test
     public void testForceRemoveActiveAdmin() throws Exception {
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
 
@@ -802,7 +814,7 @@
                 /* appId= */ 10138,
                 /* flags= */ ApplicationInfo.FLAG_TEST_ONLY);
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
-        assertTrue(dpm.isAdminActive(admin1));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
 
         // Calling from a non-shell uid should fail with a SecurityException
         mContext.binder.callingUid = 123456;
@@ -815,7 +827,7 @@
 
         mContext.callerPermissions.add(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
         // Verify
-        assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
         verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
                 null, CALLER_USER_HANDLE);
     }
@@ -825,6 +837,7 @@
      *
      * Validates that when the password history length is set, it is persisted after rebooting
      */
+    @Test
     public void testSaveAndLoadPasswordHistoryLength_persistedAfterReboot() throws Exception {
         int passwordHistoryLength = 2;
 
@@ -842,13 +855,13 @@
         // Save password history length
         dpm.setPasswordHistoryLength(admin1, passwordHistoryLength);
 
-        assertEquals(dpm.getPasswordHistoryLength(admin1), passwordHistoryLength);
+        assertThat(passwordHistoryLength).isEqualTo(dpm.getPasswordHistoryLength(admin1));
 
         initializeDpms();
         reset(mContext.spiedContext);
 
         // Password history length should persist after rebooted
-        assertEquals(dpm.getPasswordHistoryLength(admin1), passwordHistoryLength);
+        assertThat(passwordHistoryLength).isEqualTo(dpm.getPasswordHistoryLength(admin1));
     }
 
     /**
@@ -858,6 +871,7 @@
      * {@link DeviceAdminReceiver#ACTION_PASSWORD_CHANGED} is sent to managed profile owners, in
      * addition to ones in the original user.
      */
+    @Test
     public void testSetActivePasswordState_sendToProfiles() throws Exception {
         mContext.callerPermissions.add(permission.BIND_DEVICE_ADMIN);
 
@@ -893,6 +907,7 @@
      * intent {@link DeviceAdminReceiver#ACTION_PASSWORD_CHANGED} is only sent to the profile, not
      * its parent.
      */
+    @Test
     public void testSetActivePasswordState_notSentToParent() throws Exception {
         mContext.callerPermissions.add(permission.BIND_DEVICE_ADMIN);
 
@@ -932,6 +947,7 @@
     /**
      * Test for: {@link DevicePolicyManager#setDeviceOwner} DO on system user installs successfully.
      */
+    @Test
     public void testSetDeviceOwner() throws Exception {
         setDeviceOwner();
 
@@ -944,7 +960,7 @@
 
         // DO admin can't be deactivated.
         dpm.removeActiveAdmin(admin1);
-        assertTrue(dpm.isAdminActive(admin1));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
 
         // TODO Test getDeviceOwnerName() too. To do so, we need to change
         // DPMS.getApplicationLabel() because Context.createPackageContextAsUser() is not mockable.
@@ -969,19 +985,19 @@
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
 
         // Fire!
-        assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
+        assertThat(dpm.setDeviceOwner(admin1, "owner-name")).isTrue();
 
         // getDeviceOwnerComponent should return the admin1 component.
-        assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
-        assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+        assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
+        assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
 
         // Check various get APIs.
         checkGetDeviceOwnerInfoApi(dpm, /* hasDeviceOwner =*/ true);
 
         // getDeviceOwnerComponent should *NOT* return the admin1 component for other users.
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
-        assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
-        assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+        assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
+        assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
 
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
 
@@ -997,7 +1013,7 @@
                 MockUtils.checkIntentAction(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED),
                 MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
 
-        assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+        assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
     }
 
     private void checkGetDeviceOwnerInfoApi(DevicePolicyManager dpm, boolean hasDeviceOwner) {
@@ -1012,89 +1028,89 @@
         // TODO Test getDeviceOwnerName() too.  To do so, we need to change
         // DPMS.getApplicationLabel() because Context.createPackageContextAsUser() is not mockable.
         if (hasDeviceOwner) {
-            assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
-            assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
-            assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+            assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue();
+            assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isTrue();
+            assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
 
-            assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
-            assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
-            assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+            assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isTrue();
+            assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
+            assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
         } else {
-            assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
-            assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
-            assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+            assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+            assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+            assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
 
-            assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
-            assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
-            assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+            assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isFalse();
+            assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(null);
+            assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
         }
 
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         if (hasDeviceOwner) {
-            assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
-            assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
-            assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+            assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue();
+            assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isTrue();
+            assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
 
-            assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
-            assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
-            assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+            assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isTrue();
+            assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
+            assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
         } else {
-            assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
-            assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
-            assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+            assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+            assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+            assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
 
-            assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
-            assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
-            assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+            assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isFalse();
+            assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(null);
+            assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
         }
 
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         // Still with MANAGE_USERS.
-        assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
-        assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
-        assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+        assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+        assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+        assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
 
         if (hasDeviceOwner) {
-            assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
-            assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
-            assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+            assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isTrue();
+            assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
+            assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
         } else {
-            assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
-            assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
-            assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+            assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isFalse();
+            assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(null);
+            assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
         }
 
         mContext.binder.callingUid = Process.SYSTEM_UID;
         mContext.callerPermissions.remove(permission.MANAGE_USERS);
         // System can still call "OnAnyUser" without MANAGE_USERS.
         if (hasDeviceOwner) {
-            assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
-            assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
-            assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+            assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue();
+            assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isTrue();
+            assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
 
-            assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
-            assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
-            assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+            assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isTrue();
+            assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
+            assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
         } else {
-            assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
-            assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
-            assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+            assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+            assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+            assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
 
-            assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
-            assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
-            assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+            assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isFalse();
+            assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(null);
+            assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
         }
 
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         // Still no MANAGE_USERS.
         if (hasDeviceOwner) {
-            assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
-            assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
-            assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+            assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue();
+            assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isTrue();
+            assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
         } else {
-            assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
-            assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
-            assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+            assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+            assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+            assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
         }
 
         assertExpectException(SecurityException.class, /* messageRegex =*/ null,
@@ -1108,9 +1124,9 @@
 
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         // Still no MANAGE_USERS.
-        assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
-        assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
-        assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+        assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+        assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+        assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
 
         assertExpectException(SecurityException.class, /* messageRegex =*/ null,
                 () -> dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
@@ -1130,6 +1146,7 @@
     /**
      * Test for: {@link DevicePolicyManager#setDeviceOwner} Package doesn't exist.
      */
+    @Test
     public void testSetDeviceOwner_noSuchPackage() {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -1144,10 +1161,12 @@
                 () -> dpm.setDeviceOwner(new ComponentName("a.b.c", ".def")));
     }
 
+    @Test
     public void testSetDeviceOwner_failures() throws Exception {
         // TODO Test more failure cases.  Basically test all chacks in enforceCanSetDeviceOwner().
     }
 
+    @Test
     public void testClearDeviceOwner() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -1164,20 +1183,20 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
-        assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
+        assertThat(dpm.setDeviceOwner(admin1, "owner-name")).isTrue();
 
         // Verify internal calls.
         verify(getServices().iactivityManager, times(1)).updateDeviceOwner(
                 eq(admin1.getPackageName()));
 
-        assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+        assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
 
         dpm.addUserRestriction(admin1, UserManager.DISALLOW_ADD_USER);
         when(getServices().userManager.hasUserRestriction(eq(UserManager.DISALLOW_ADD_USER),
                 MockUtils.checkUserHandle(UserHandle.USER_SYSTEM))).thenReturn(true);
 
-        assertTrue(dpm.isAdminActive(admin1));
-        assertFalse(dpm.isRemovingAdmin(admin1, UserHandle.USER_SYSTEM));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
+        assertThat(dpm.isRemovingAdmin(admin1, UserHandle.USER_SYSTEM)).isFalse();
 
         // Set up other mocks.
         when(getServices().userManager.getUserRestrictions()).thenReturn(new Bundle());
@@ -1196,7 +1215,7 @@
         dpm.clearDeviceOwnerApp(admin1.getPackageName());
 
         // Now DO shouldn't be set.
-        assertNull(dpm.getDeviceOwnerComponentOnAnyUser());
+        assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isNull();
 
         verify(getServices().userManager).setUserRestriction(eq(UserManager.DISALLOW_ADD_USER),
                 eq(false),
@@ -1209,7 +1228,7 @@
         verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
                 null, UserHandle.USER_SYSTEM);
 
-        assertFalse(dpm.isAdminActiveAsUser(admin1, UserHandle.USER_SYSTEM));
+        assertThat(dpm.isAdminActiveAsUser(admin1, UserHandle.USER_SYSTEM)).isFalse();
 
         // ACTION_DEVICE_OWNER_CHANGED should be sent twice, once for setting the device owner
         // and once for clearing it.
@@ -1219,6 +1238,7 @@
         // TODO Check other calls.
     }
 
+    @Test
     public void testDeviceOwnerBackupActivateDeactivate() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -1227,7 +1247,7 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
-        assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
+        assertThat(dpm.setDeviceOwner(admin1, "owner-name")).isTrue();
 
         verify(getServices().ibackupManager, times(1)).setBackupServiceActive(
                 eq(UserHandle.USER_SYSTEM), eq(false));
@@ -1238,6 +1258,7 @@
                 eq(UserHandle.USER_SYSTEM), eq(true));
     }
 
+    @Test
     public void testProfileOwnerBackupActivateDeactivate() throws Exception {
         setAsProfileOwner(admin1);
 
@@ -1250,6 +1271,7 @@
                 eq(CALLER_USER_HANDLE), eq(true));
     }
 
+    @Test
     public void testClearDeviceOwner_fromDifferentUser() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -1266,13 +1288,13 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
-        assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
+        assertThat(dpm.setDeviceOwner(admin1, "owner-name")).isTrue();
 
         // Verify internal calls.
         verify(getServices().iactivityManager, times(1)).updateDeviceOwner(
                 eq(admin1.getPackageName()));
 
-        assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+        assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
 
         // Now call clear from the secondary user, which should throw.
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
@@ -1286,7 +1308,7 @@
                 () -> dpm.clearDeviceOwnerApp(admin1.getPackageName()));
 
         // DO shouldn't be removed.
-        assertTrue(dpm.isDeviceManaged());
+        assertThat(dpm.isDeviceManaged()).isTrue();
     }
 
     /**
@@ -1294,6 +1316,7 @@
      *
      * Validates that when the device owner is removed, the reset password token is cleared
      */
+    @Test
     public void testClearDeviceOwner_clearResetPasswordToken() throws Exception {
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -1312,13 +1335,13 @@
         when(getServices().lockPatternUtils.addEscrowToken(eq(token), eq(UserHandle.USER_SYSTEM),
                 nullable(EscrowTokenStateChangeCallback.class)))
                 .thenReturn(handle);
-        assertTrue(dpm.setResetPasswordToken(admin1, token));
+        assertThat(dpm.setResetPasswordToken(admin1, token)).isTrue();
 
         // Assert reset password token is active
         when(getServices().lockPatternUtils.isEscrowTokenActive(eq(handle),
                 eq(UserHandle.USER_SYSTEM)))
                 .thenReturn(true);
-        assertTrue(dpm.isResetPasswordTokenActive(admin1));
+        assertThat(dpm.isResetPasswordTokenActive(admin1)).isTrue();
 
         // Remove the device owner
         dpm.clearDeviceOwnerApp(admin1.getPackageName());
@@ -1328,12 +1351,13 @@
                 eq(UserHandle.USER_SYSTEM));
     }
 
+    @Test
     public void testSetProfileOwner() throws Exception {
         setAsProfileOwner(admin1);
 
         // PO admin can't be deactivated.
         dpm.removeActiveAdmin(admin1);
-        assertTrue(dpm.isAdminActive(admin1));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
 
         // Try setting DO on the same user, which should fail.
         setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID);
@@ -1347,13 +1371,14 @@
         });
     }
 
+    @Test
     public void testClearProfileOwner() throws Exception {
         setAsProfileOwner(admin1);
 
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
 
-        assertTrue(dpm.isProfileOwnerApp(admin1.getPackageName()));
-        assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isProfileOwnerApp(admin1.getPackageName())).isTrue();
+        assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
 
         // First try when the user is locked, which should fail.
         when(getServices().userManager.isUserUnlocked(anyInt()))
@@ -1367,16 +1392,18 @@
         dpm.clearProfileOwner(admin1);
 
         // Check
-        assertFalse(dpm.isProfileOwnerApp(admin1.getPackageName()));
-        assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+        assertThat(dpm.isProfileOwnerApp(admin1.getPackageName())).isFalse();
+        assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
         verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
                 null, CALLER_USER_HANDLE);
     }
 
+    @Test
     public void testSetProfileOwner_failures() throws Exception {
         // TODO Test more failure cases.  Basically test all chacks in enforceCanSetProfileOwner().
     }
 
+    @Test
     public void testGetDeviceOwnerAdminLocked() throws Exception {
         checkDeviceOwnerWithMultipleDeviceAdmins();
     }
@@ -1421,13 +1448,13 @@
 
         // Set DO on the first non-system user.
         getServices().setUserRunning(CALLER_USER_HANDLE, true);
-        assertTrue(dpm.setDeviceOwner(admin2, "owner-name", CALLER_USER_HANDLE));
+        assertThat(dpm.setDeviceOwner(admin2, "owner-name", CALLER_USER_HANDLE)).isTrue();
 
-        assertEquals(admin2, dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false));
+        assertThat(dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false)).isEqualTo(admin2);
 
         // Then check getDeviceOwnerAdminLocked().
-        assertEquals(admin2, getDeviceOwner().info.getComponent());
-        assertEquals(DpmMockContext.CALLER_UID, getDeviceOwner().getUid());
+        assertThat(getDeviceOwner().info.getComponent()).isEqualTo(admin2);
+        assertThat(getDeviceOwner().getUid()).isEqualTo(DpmMockContext.CALLER_UID);
     }
 
     /**
@@ -1438,6 +1465,7 @@
      * We didn't use to persist the DO component class name, but now we do, and the above method
      * finds the right component from a package name upon migration.
      */
+    @Test
     public void testDeviceOwnerMigration() throws Exception {
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
         checkDeviceOwnerWithMultipleDeviceAdmins();
@@ -1449,7 +1477,8 @@
         dpms.mOwners.writeDeviceOwner();
 
         // Make sure the DO component name doesn't have a class name.
-        assertEquals("", dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false).getClassName());
+        assertThat(dpms.getDeviceOwnerComponent(/* callingUserOnly= */ false).getClassName())
+                .isEmpty();
 
         // Then create a new DPMS to have it load the settings from files.
         when(getServices().userManager.getUserRestrictions(any(UserHandle.class)))
@@ -1459,9 +1488,10 @@
         // Now the DO component name is a full name.
         // *BUT* because both admin1 and admin2 belong to the same package, we think admin1 is the
         // DO.
-        assertEquals(admin1, dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false));
+        assertThat(dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false)).isEqualTo(admin1);
     }
 
+    @Test
     public void testSetGetApplicationRestriction() {
         setAsProfileOwner(admin1);
         mContext.packageName = admin1.getPackageName();
@@ -1480,20 +1510,20 @@
 
         {
             Bundle returned = dpm.getApplicationRestrictions(admin1, "pkg1");
-            assertNotNull(returned);
-            assertEquals(returned.size(), 1);
-            assertEquals(returned.get("KEY_STRING"), "Foo1");
+            assertThat(returned).isNotNull();
+            assertThat(returned.size()).isEqualTo(1);
+            assertThat("Foo1").isEqualTo(returned.get("KEY_STRING"));
         }
 
         {
             Bundle returned = dpm.getApplicationRestrictions(admin1, "pkg2");
-            assertNotNull(returned);
-            assertEquals(returned.size(), 1);
-            assertEquals(returned.get("KEY_STRING"), "Foo2");
+            assertThat(returned).isNotNull();
+            assertThat(returned.size()).isEqualTo(1);
+            assertThat("Foo2").isEqualTo(returned.get("KEY_STRING"));
         }
 
         dpm.setApplicationRestrictions(admin1, "pkg2", new Bundle());
-        assertEquals(0, dpm.getApplicationRestrictions(admin1, "pkg2").size());
+        assertThat(dpm.getApplicationRestrictions(admin1, "pkg2").size()).isEqualTo(0);
     }
 
     /**
@@ -1546,6 +1576,7 @@
         return uid;
     }
 
+    @Test
     public void testCertificateDisclosure() throws Exception {
         final int userId = CALLER_USER_HANDLE;
         final UserHandle user = UserHandle.of(userId);
@@ -1571,7 +1602,8 @@
                 .cancelAsUser(anyString(), anyInt(), eq(user));
 
         // Given that we have four certificates installed,
-        when(getServices().keyChainConnection.getService().getUserCaAliases()).thenReturn(fourCerts);
+        when(getServices().keyChainConnection.getService().getUserCaAliases())
+                .thenReturn(fourCerts);
         // when two of them are approved (one of them approved twice hence no action),
         dpms.approveCaCert(fourCerts.getList().get(0), userId, true);
         dpms.approveCaCert(fourCerts.getList().get(1), userId, true);
@@ -1586,6 +1618,7 @@
      * Simple test for delegate set/get and general delegation. Tests verifying that delegated
      * privileges can acually be exercised by a delegate are not covered here.
      */
+    @Test
     public void testDelegation() throws Exception {
         setAsProfileOwner(admin1);
 
@@ -1606,17 +1639,18 @@
 
         // DPMS correctly stores and retrieves the delegates
         DevicePolicyData policy = dpms.mUserData.get(userHandle);
-        assertEquals(2, policy.mDelegationMap.size());
+        assertThat(policy.mDelegationMap.size()).isEqualTo(2);
         MoreAsserts.assertContentsInAnyOrder(policy.mDelegationMap.get(CERT_DELEGATE),
             DELEGATION_CERT_INSTALL);
         MoreAsserts.assertContentsInAnyOrder(dpm.getDelegatedScopes(admin1, CERT_DELEGATE),
             DELEGATION_CERT_INSTALL);
-        assertEquals(CERT_DELEGATE, dpm.getCertInstallerPackage(admin1));
+        assertThat(dpm.getCertInstallerPackage(admin1)).isEqualTo(CERT_DELEGATE);
         MoreAsserts.assertContentsInAnyOrder(policy.mDelegationMap.get(RESTRICTIONS_DELEGATE),
             DELEGATION_APP_RESTRICTIONS);
         MoreAsserts.assertContentsInAnyOrder(dpm.getDelegatedScopes(admin1, RESTRICTIONS_DELEGATE),
             DELEGATION_APP_RESTRICTIONS);
-        assertEquals(RESTRICTIONS_DELEGATE, dpm.getApplicationRestrictionsManagingPackage(admin1));
+        assertThat(dpm.getApplicationRestrictionsManagingPackage(admin1))
+                .isEqualTo(RESTRICTIONS_DELEGATE);
 
         // On calling install certificate APIs from an unauthorized process
         mContext.binder.callingUid = RESTRICTIONS_DELEGATE_UID;
@@ -1658,6 +1692,7 @@
         }
     }
 
+    @Test
     public void testApplicationRestrictionsManagingApp() throws Exception {
         setAsProfileOwner(admin1);
 
@@ -1673,7 +1708,7 @@
         // delegated that permission yet.
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         mContext.packageName = admin1.getPackageName();
-        assertFalse(dpm.isCallerApplicationRestrictionsManagingPackage());
+        assertThat(dpm.isCallerApplicationRestrictionsManagingPackage()).isFalse();
         final Bundle rest = new Bundle();
         rest.putString("KEY_STRING", "Foo1");
         assertExpectException(SecurityException.class, INVALID_CALLING_IDENTITY_MSG,
@@ -1682,7 +1717,7 @@
         // Check via the profile owner that no restrictions were set.
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         mContext.packageName = admin1.getPackageName();
-        assertEquals(0, dpm.getApplicationRestrictions(admin1, "pkg1").size());
+        assertThat(dpm.getApplicationRestrictions(admin1, "pkg1").size()).isEqualTo(0);
 
         // Check the API does not allow setting a non-existent package
         assertExpectException(PackageManager.NameNotFoundException.class,
@@ -1692,22 +1727,22 @@
 
         // Let appRestrictionsManagerPackage manage app restrictions
         dpm.setApplicationRestrictionsManagingPackage(admin1, appRestrictionsManagerPackage);
-        assertEquals(appRestrictionsManagerPackage,
-                dpm.getApplicationRestrictionsManagingPackage(admin1));
+        assertThat(dpm.getApplicationRestrictionsManagingPackage(admin1))
+                .isEqualTo(appRestrictionsManagerPackage);
 
         // Now that package should be able to set and retrieve app restrictions.
         mContext.binder.callingUid = appRestrictionsManagerUid;
         mContext.packageName = appRestrictionsManagerPackage;
-        assertTrue(dpm.isCallerApplicationRestrictionsManagingPackage());
+        assertThat(dpm.isCallerApplicationRestrictionsManagingPackage()).isTrue();
         dpm.setApplicationRestrictions(null, "pkg1", rest);
         Bundle returned = dpm.getApplicationRestrictions(null, "pkg1");
-        assertEquals(1, returned.size(), 1);
-        assertEquals("Foo1", returned.get("KEY_STRING"));
+        assertThat(returned.size()).isEqualTo(1);
+        assertThat(returned.get("KEY_STRING")).isEqualTo("Foo1");
 
         // The same app running on a separate user shouldn't be able to manage app restrictions.
         mContext.binder.callingUid = UserHandle.getUid(
                 UserHandle.USER_SYSTEM, appRestrictionsManagerAppId);
-        assertFalse(dpm.isCallerApplicationRestrictionsManagingPackage());
+        assertThat(dpm.isCallerApplicationRestrictionsManagingPackage()).isFalse();
         assertExpectException(SecurityException.class, nonDelegateExceptionMessageRegex,
                 () -> dpm.setApplicationRestrictions(null, "pkg1", rest));
 
@@ -1715,20 +1750,21 @@
         // too.
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         mContext.packageName = admin1.getPackageName();
-        assertEquals(returned, dpm.getApplicationRestrictions(admin1, "pkg1"));
+        assertThat(dpm.getApplicationRestrictions(admin1, "pkg1")).isEqualTo(returned);
         dpm.setApplicationRestrictions(admin1, "pkg1", null);
-        assertEquals(0, dpm.getApplicationRestrictions(admin1, "pkg1").size());
+        assertThat(dpm.getApplicationRestrictions(admin1, "pkg1").size()).isEqualTo(0);
 
         // Removing the ability for the package to manage app restrictions.
         dpm.setApplicationRestrictionsManagingPackage(admin1, null);
-        assertNull(dpm.getApplicationRestrictionsManagingPackage(admin1));
+        assertThat(dpm.getApplicationRestrictionsManagingPackage(admin1)).isNull();
         mContext.binder.callingUid = appRestrictionsManagerUid;
         mContext.packageName = appRestrictionsManagerPackage;
-        assertFalse(dpm.isCallerApplicationRestrictionsManagingPackage());
+        assertThat(dpm.isCallerApplicationRestrictionsManagingPackage()).isFalse();
         assertExpectException(SecurityException.class, INVALID_CALLING_IDENTITY_MSG,
                 () -> dpm.setApplicationRestrictions(null, "pkg1", null));
     }
 
+    @Test
     public void testSetUserRestriction_asDo() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -1745,8 +1781,8 @@
 
         // Call.
         dpm.setActiveAdmin(admin1, /* replace =*/ false, UserHandle.USER_SYSTEM);
-        assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
-                UserHandle.USER_SYSTEM));
+        assertThat(dpm.setDeviceOwner(admin1, "owner-name",
+        UserHandle.USER_SYSTEM)).isTrue();
 
         assertNoDeviceOwnerRestrictions();
         reset(getServices().userManagerInternal);
@@ -1859,6 +1895,7 @@
         return null;
     }
 
+    @Test
     public void testDaDisallowedPolicies_SecurityException() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
@@ -1869,25 +1906,28 @@
         boolean originalCameraDisabled = dpm.getCameraDisabled(admin1);
         assertExpectException(SecurityException.class, /* messageRegex= */ null,
                 () -> dpm.setCameraDisabled(admin1, true));
-        assertEquals(originalCameraDisabled, dpm.getCameraDisabled(admin1));
+        assertThat(dpm.getCameraDisabled(admin1)).isEqualTo(originalCameraDisabled);
 
         int originalKeyguardDisabledFeatures = dpm.getKeyguardDisabledFeatures(admin1);
         assertExpectException(SecurityException.class, /* messageRegex= */ null,
                 () -> dpm.setKeyguardDisabledFeatures(admin1,
                         DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL));
-        assertEquals(originalKeyguardDisabledFeatures, dpm.getKeyguardDisabledFeatures(admin1));
+        assertThat(dpm.getKeyguardDisabledFeatures(admin1))
+                .isEqualTo(originalKeyguardDisabledFeatures);
 
         long originalPasswordExpirationTimeout = dpm.getPasswordExpirationTimeout(admin1);
         assertExpectException(SecurityException.class, /* messageRegex= */ null,
                 () -> dpm.setPasswordExpirationTimeout(admin1, 1234));
-        assertEquals(originalPasswordExpirationTimeout, dpm.getPasswordExpirationTimeout(admin1));
+        assertThat(dpm.getPasswordExpirationTimeout(admin1))
+                .isEqualTo(originalPasswordExpirationTimeout);
 
         int originalPasswordQuality = dpm.getPasswordQuality(admin1);
         assertExpectException(SecurityException.class, /* messageRegex= */ null,
                 () -> dpm.setPasswordQuality(admin1, DevicePolicyManager.PASSWORD_QUALITY_NUMERIC));
-        assertEquals(originalPasswordQuality, dpm.getPasswordQuality(admin1));
+        assertThat(dpm.getPasswordQuality(admin1)).isEqualTo(originalPasswordQuality);
     }
 
+    @Test
     public void testSetUserRestriction_asPo() {
         setAsProfileOwner(admin1);
 
@@ -2023,6 +2063,7 @@
                     UserManager.DISALLOW_UNMUTE_MICROPHONE
             );
 
+    @Test
     public void testSetUserRestriction_asPoOfOrgOwnedDevice() throws Exception {
         final int MANAGED_PROFILE_ADMIN_UID =
                 UserHandle.getUid(CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID);
@@ -2097,6 +2138,7 @@
         );
     }
 
+    @Test
     public void testNoDefaultEnabledUserRestrictions() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -2112,8 +2154,8 @@
         setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
 
         dpm.setActiveAdmin(admin1, /* replace =*/ false, UserHandle.USER_SYSTEM);
-        assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
-                UserHandle.USER_SYSTEM));
+        assertThat(dpm.setDeviceOwner(admin1, "owner-name",
+        UserHandle.USER_SYSTEM)).isTrue();
 
         assertNoDeviceOwnerRestrictions();
 
@@ -2132,6 +2174,7 @@
         );
     }
 
+    @Test
     public void testSetFactoryResetProtectionPolicyWithDO() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -2156,6 +2199,7 @@
                 eq(android.Manifest.permission.MANAGE_FACTORY_RESET_PROTECTION));
     }
 
+    @Test
     public void testSetFactoryResetProtectionPolicyFailWithPO() throws Exception {
         setupProfileOwner();
 
@@ -2167,6 +2211,7 @@
                 () -> dpm.setFactoryResetProtectionPolicy(admin1, policy));
     }
 
+    @Test
     public void testSetFactoryResetProtectionPolicyWithPOOfOrganizationOwnedDevice()
             throws Exception {
         setupProfileOwner();
@@ -2204,6 +2249,7 @@
                 eq(android.Manifest.permission.MANAGE_FACTORY_RESET_PROTECTION));
     }
 
+    @Test
     public void testGetFactoryResetProtectionPolicyWithFrpManagementAgent()
             throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -2245,6 +2291,7 @@
         assertThat(actualAccounts).containsExactlyElementsIn(expectedAccounts);
     }
 
+    @Test
     public void testSetKeyguardDisabledFeaturesWithDO() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -2255,6 +2302,7 @@
                 DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA);
     }
 
+    @Test
     public void testSetKeyguardDisabledFeaturesWithPO() throws Exception {
         setupProfileOwner();
 
@@ -2264,6 +2312,7 @@
                 DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
     }
 
+    @Test
     public void testSetKeyguardDisabledFeaturesWithPOOfOrganizationOwnedDevice()
             throws Exception {
         final int MANAGED_PROFILE_USER_ID = CALLER_USER_HANDLE;
@@ -2281,6 +2330,7 @@
                 DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA);
     }
 
+    @Test
     public void testSetApplicationHiddenWithDO() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -2304,6 +2354,7 @@
                 UserHandle.USER_SYSTEM);
     }
 
+    @Test
     public void testSetApplicationHiddenWithPOOfOrganizationOwnedDevice() throws Exception {
         final int MANAGED_PROFILE_USER_ID = CALLER_USER_HANDLE;
         final int MANAGED_PROFILE_ADMIN_UID =
@@ -2334,6 +2385,7 @@
                 false, UserHandle.USER_SYSTEM);
     }
 
+    @Test
     public void testGetMacAddress() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -2351,7 +2403,7 @@
 
         // DO needs to be an DA.
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
-        assertTrue(dpm.isAdminActive(admin1));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
 
         // Test 2. Caller has DA, but not DO.
         assertExpectException(SecurityException.class,
@@ -2359,7 +2411,7 @@
                 () -> dpm.getWifiMacAddress(admin1));
 
         // Test 3. Caller has PO, but not DO.
-        assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM));
+        assertThat(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
         assertExpectException(SecurityException.class,
                 /* messageRegex= */ INVALID_CALLING_IDENTITY_MSG,
                 () -> dpm.getWifiMacAddress(admin1));
@@ -2368,30 +2420,32 @@
         dpm.clearProfileOwner(admin1);
         dpm.setActiveAdmin(admin1, false);
         // Test 4, Caller is DO now.
-        assertTrue(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM));
+        assertThat(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
 
         // 4-1.  But WifiManager is not ready.
-        assertNull(dpm.getWifiMacAddress(admin1));
+        assertThat(dpm.getWifiMacAddress(admin1)).isNull();
 
         // 4-2.  When WifiManager returns an empty array, dpm should also output null.
         when(getServices().wifiManager.getFactoryMacAddresses()).thenReturn(new String[0]);
-        assertNull(dpm.getWifiMacAddress(admin1));
+        assertThat(dpm.getWifiMacAddress(admin1)).isNull();
 
         // 4-3. With a real MAC address.
         final String[] macAddresses = new String[]{"11:22:33:44:55:66"};
         when(getServices().wifiManager.getFactoryMacAddresses()).thenReturn(macAddresses);
-        assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1));
+        assertThat(dpm.getWifiMacAddress(admin1)).isEqualTo("11:22:33:44:55:66");
     }
 
+    @Test
     public void testGetMacAddressByOrgOwnedPO() throws Exception {
         setupProfileOwner();
         configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
 
         final String[] macAddresses = new String[]{"11:22:33:44:55:66"};
         when(getServices().wifiManager.getFactoryMacAddresses()).thenReturn(macAddresses);
-        assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1));
+        assertThat(dpm.getWifiMacAddress(admin1)).isEqualTo("11:22:33:44:55:66");
     }
 
+    @Test
     public void testReboot() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -2404,19 +2458,19 @@
 
         // Set admin1 as DA.
         dpm.setActiveAdmin(admin1, false);
-        assertTrue(dpm.isAdminActive(admin1));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
         assertExpectException(SecurityException.class, /* messageRegex= */
                 INVALID_CALLING_IDENTITY_MSG, () -> dpm.reboot(admin1));
 
         // Set admin1 as PO.
-        assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM));
+        assertThat(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
         assertExpectException(SecurityException.class, /* messageRegex= */
                 INVALID_CALLING_IDENTITY_MSG, () -> dpm.reboot(admin1));
 
         // Remove PO and add DO.
         dpm.clearProfileOwner(admin1);
         dpm.setActiveAdmin(admin1, false);
-        assertTrue(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM));
+        assertThat(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
 
         // admin1 is DO.
         // Set current call state of device to ringing.
@@ -2432,10 +2486,12 @@
                 () -> dpm.reboot(admin1));
 
         // Set current call state of device to idle.
-        when(getServices().telephonyManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_IDLE);
+        when(getServices().telephonyManager.getCallState())
+                .thenReturn(TelephonyManager.CALL_STATE_IDLE);
         dpm.reboot(admin1);
     }
 
+    @Test
     public void testSetGetSupportText() {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         dpm.setActiveAdmin(admin1, true);
@@ -2444,11 +2500,11 @@
 
         // Null default support messages.
         {
-            assertNull(dpm.getLongSupportMessage(admin1));
-            assertNull(dpm.getShortSupportMessage(admin1));
+            assertThat(dpm.getLongSupportMessage(admin1)).isNull();
+            assertThat(dpm.getShortSupportMessage(admin1)).isNull();
             mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-            assertNull(dpm.getShortSupportMessageForUser(admin1, CALLER_USER_HANDLE));
-            assertNull(dpm.getLongSupportMessageForUser(admin1, CALLER_USER_HANDLE));
+            assertThat(dpm.getShortSupportMessageForUser(admin1, CALLER_USER_HANDLE)).isNull();
+            assertThat(dpm.getLongSupportMessageForUser(admin1, CALLER_USER_HANDLE)).isNull();
             mMockContext.binder.callingUid = DpmMockContext.CALLER_UID;
         }
 
@@ -2473,46 +2529,46 @@
         {
             final String supportText = "Some text to test with.";
             dpm.setShortSupportMessage(admin1, supportText);
-            assertEquals(supportText, dpm.getShortSupportMessage(admin1));
-            assertNull(dpm.getLongSupportMessage(admin1));
-            assertNull(dpm.getShortSupportMessage(admin2));
+            assertThat(dpm.getShortSupportMessage(admin1)).isEqualTo(supportText);
+            assertThat(dpm.getLongSupportMessage(admin1)).isNull();
+            assertThat(dpm.getShortSupportMessage(admin2)).isNull();
 
             mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-            assertEquals(supportText, dpm.getShortSupportMessageForUser(admin1,
-                    CALLER_USER_HANDLE));
-            assertNull(dpm.getShortSupportMessageForUser(admin2, CALLER_USER_HANDLE));
-            assertNull(dpm.getLongSupportMessageForUser(admin1, CALLER_USER_HANDLE));
+            assertThat(dpm.getShortSupportMessageForUser(admin1,
+            CALLER_USER_HANDLE)).isEqualTo(supportText);
+            assertThat(dpm.getShortSupportMessageForUser(admin2, CALLER_USER_HANDLE)).isNull();
+            assertThat(dpm.getLongSupportMessageForUser(admin1, CALLER_USER_HANDLE)).isNull();
             mMockContext.binder.callingUid = DpmMockContext.CALLER_UID;
 
             dpm.setShortSupportMessage(admin1, null);
-            assertNull(dpm.getShortSupportMessage(admin1));
+            assertThat(dpm.getShortSupportMessage(admin1)).isNull();
         }
 
         // Set/Get long returns what it sets and other admins text isn't changed.
         {
             final String supportText = "Some text to test with.\nWith more text.";
             dpm.setLongSupportMessage(admin1, supportText);
-            assertEquals(supportText, dpm.getLongSupportMessage(admin1));
-            assertNull(dpm.getShortSupportMessage(admin1));
-            assertNull(dpm.getLongSupportMessage(admin2));
+            assertThat(dpm.getLongSupportMessage(admin1)).isEqualTo(supportText);
+            assertThat(dpm.getShortSupportMessage(admin1)).isNull();
+            assertThat(dpm.getLongSupportMessage(admin2)).isNull();
 
             mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-            assertEquals(supportText, dpm.getLongSupportMessageForUser(admin1,
-                    CALLER_USER_HANDLE));
-            assertNull(dpm.getLongSupportMessageForUser(admin2, CALLER_USER_HANDLE));
-            assertNull(dpm.getShortSupportMessageForUser(admin1, CALLER_USER_HANDLE));
+            assertThat(dpm.getLongSupportMessageForUser(admin1,
+            CALLER_USER_HANDLE)).isEqualTo(supportText);
+            assertThat(dpm.getLongSupportMessageForUser(admin2, CALLER_USER_HANDLE)).isNull();
+            assertThat(dpm.getShortSupportMessageForUser(admin1, CALLER_USER_HANDLE)).isNull();
             mMockContext.binder.callingUid = DpmMockContext.CALLER_UID;
 
             dpm.setLongSupportMessage(admin1, null);
-            assertNull(dpm.getLongSupportMessage(admin1));
+            assertThat(dpm.getLongSupportMessage(admin1)).isNull();
         }
     }
 
+    @Test
     public void testSetGetMeteredDataDisabledPackages() throws Exception {
         setAsProfileOwner(admin1);
 
-        final ArrayList<String> emptyList = new ArrayList<>();
-        assertEquals(emptyList, dpm.getMeteredDataDisabledPackages(admin1));
+        assertThat(dpm.getMeteredDataDisabledPackages(admin1)).isEmpty();
 
         // Setup
         final ArrayList<String> pkgsToRestrict = new ArrayList<>();
@@ -2525,8 +2581,8 @@
         List<String> excludedPkgs = dpm.setMeteredDataDisabledPackages(admin1, pkgsToRestrict);
 
         // Verify
-        assertEquals(emptyList, excludedPkgs);
-        assertEquals(pkgsToRestrict, dpm.getMeteredDataDisabledPackages(admin1));
+        assertThat(excludedPkgs).isEmpty();
+        assertThat(dpm.getMeteredDataDisabledPackages(admin1)).isEqualTo(pkgsToRestrict);
         verify(getServices().networkPolicyManagerInternal).setMeteredRestrictedPackages(
                 MockUtils.checkApps(pkgsToRestrict.toArray(new String[0])),
                 eq(CALLER_USER_HANDLE));
@@ -2536,17 +2592,18 @@
         excludedPkgs = dpm.setMeteredDataDisabledPackages(admin1, pkgsToRestrict);
 
         // Verify
-        assertEquals(emptyList, excludedPkgs);
-        assertEquals(pkgsToRestrict, dpm.getMeteredDataDisabledPackages(admin1));
+        assertThat(excludedPkgs).isEmpty();
+        assertThat(dpm.getMeteredDataDisabledPackages(admin1)).isEqualTo(pkgsToRestrict);
         verify(getServices().networkPolicyManagerInternal).setMeteredRestrictedPackages(
                 MockUtils.checkApps(pkgsToRestrict.toArray(new String[0])),
                 eq(CALLER_USER_HANDLE));
     }
 
+    @Test
     public void testSetGetMeteredDataDisabledPackages_deviceAdmin() {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         dpm.setActiveAdmin(admin1, true);
-        assertTrue(dpm.isAdminActive(admin1));
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
         mContext.callerPermissions.remove(permission.MANAGE_DEVICE_ADMINS);
 
         assertExpectException(SecurityException.class,  /* messageRegex= */ NOT_PROFILE_OWNER_MSG,
@@ -2555,11 +2612,11 @@
                 () -> dpm.getMeteredDataDisabledPackages(admin1));
     }
 
+    @Test
     public void testIsMeteredDataDisabledForUserPackage() throws Exception {
         setAsProfileOwner(admin1);
 
         // Setup
-        final ArrayList<String> emptyList = new ArrayList<>();
         final ArrayList<String> pkgsToRestrict = new ArrayList<>();
         final String package1 = "com.example.one";
         final String package2 = "com.example.two";
@@ -2571,16 +2628,20 @@
         List<String> excludedPkgs = dpm.setMeteredDataDisabledPackages(admin1, pkgsToRestrict);
 
         // Verify
-        assertEquals(emptyList, excludedPkgs);
+        assertThat(excludedPkgs).isEmpty();
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertTrue(package1 + "should be restricted",
-                dpm.isMeteredDataDisabledPackageForUser(admin1, package1, CALLER_USER_HANDLE));
-        assertTrue(package2 + "should be restricted",
-                dpm.isMeteredDataDisabledPackageForUser(admin1, package2, CALLER_USER_HANDLE));
-        assertFalse(package3 + "should not be restricted",
-                dpm.isMeteredDataDisabledPackageForUser(admin1, package3, CALLER_USER_HANDLE));
+        assertWithMessage("%s should be restricted", package1)
+                .that(dpm.isMeteredDataDisabledPackageForUser(admin1, package1, CALLER_USER_HANDLE))
+                .isTrue();
+        assertWithMessage("%s should be restricted", package2)
+                .that(dpm.isMeteredDataDisabledPackageForUser(admin1, package2, CALLER_USER_HANDLE))
+                .isTrue();
+        assertWithMessage("%s should not be restricted", package3)
+                .that(dpm.isMeteredDataDisabledPackageForUser(admin1, package3, CALLER_USER_HANDLE))
+                .isFalse();
     }
 
+    @Test
     public void testIsMeteredDataDisabledForUserPackage_nonSystemUidCaller() throws Exception {
         setAsProfileOwner(admin1);
         assertExpectException(SecurityException.class,
@@ -2597,6 +2658,7 @@
         clearDeviceOwner();
     }
 
+    @Test
     public void testCreateAdminSupportIntent() throws Exception {
         // Setup device owner.
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -2604,11 +2666,11 @@
 
         // Nonexisting permission returns null
         Intent intent = dpm.createAdminSupportIntent("disallow_nothing");
-        assertNull(intent);
+        assertThat(intent).isNull();
 
         // Existing permission that is not set returns null
         intent = dpm.createAdminSupportIntent(UserManager.DISALLOW_ADJUST_VOLUME);
-        assertNull(intent);
+        assertThat(intent).isNull();
 
         // Existing permission that is not set by device/profile owner returns null
         when(getServices().userManager.hasUserRestriction(
@@ -2616,7 +2678,7 @@
                 eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
                 .thenReturn(true);
         intent = dpm.createAdminSupportIntent(UserManager.DISALLOW_ADJUST_VOLUME);
-        assertNull(intent);
+        assertThat(intent).isNull();
 
         // UM.getUserRestrictionSources() will return a list of size 1 with the caller resource.
         doAnswer((Answer<List<UserManager.EnforcingUser>>) invocation -> Collections.singletonList(
@@ -2626,51 +2688,53 @@
                 eq(UserManager.DISALLOW_ADJUST_VOLUME),
                 eq(UserHandle.of(UserHandle.myUserId())));
         intent = dpm.createAdminSupportIntent(UserManager.DISALLOW_ADJUST_VOLUME);
-        assertNotNull(intent);
-        assertEquals(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS, intent.getAction());
-        assertEquals(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID),
-                intent.getIntExtra(Intent.EXTRA_USER_ID, -1));
-        assertEquals(admin1, intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN));
-        assertEquals(UserManager.DISALLOW_ADJUST_VOLUME,
-                intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
+        assertThat(intent).isNotNull();
+        assertThat(intent.getAction()).isEqualTo(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
+        assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, -1))
+                .isEqualTo(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID));
+        assertThat(
+                (ComponentName) intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN))
+                        .isEqualTo(admin1);
+        assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION))
+                .isEqualTo(UserManager.DISALLOW_ADJUST_VOLUME);
 
         // Try with POLICY_DISABLE_CAMERA and POLICY_DISABLE_SCREEN_CAPTURE, which are not
         // user restrictions
 
         // Camera is not disabled
         intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_CAMERA);
-        assertNull(intent);
+        assertThat(intent).isNull();
 
         // Camera is disabled
         dpm.setCameraDisabled(admin1, true);
         intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_CAMERA);
-        assertNotNull(intent);
-        assertEquals(DevicePolicyManager.POLICY_DISABLE_CAMERA,
-                intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
+        assertThat(intent).isNotNull();
+        assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION))
+                .isEqualTo(DevicePolicyManager.POLICY_DISABLE_CAMERA);
 
         // Screen capture is not disabled
         intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
-        assertNull(intent);
+        assertThat(intent).isNull();
 
         // Screen capture is disabled
         dpm.setScreenCaptureDisabled(admin1, true);
         intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
-        assertNotNull(intent);
-        assertEquals(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE,
-                intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
+        assertThat(intent).isNotNull();
+        assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION))
+                .isEqualTo(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
 
         // Same checks for different user
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         // Camera should be disabled by device owner
         intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_CAMERA);
-        assertNotNull(intent);
-        assertEquals(DevicePolicyManager.POLICY_DISABLE_CAMERA,
-                intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
-        assertEquals(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID),
-                intent.getIntExtra(Intent.EXTRA_USER_ID, -1));
+        assertThat(intent).isNotNull();
+        assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION))
+                .isEqualTo(DevicePolicyManager.POLICY_DISABLE_CAMERA);
+        assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, -1))
+                .isEqualTo(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID));
         // ScreenCapture should not be disabled by device owner
         intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
-        assertNull(intent);
+        assertThat(intent).isNull();
     }
 
     /**
@@ -2679,6 +2743,7 @@
      * {@link DevicePolicyManager#getAffiliationIds}
      * {@link DevicePolicyManager#isAffiliatedUser}
      */
+    @Test
     public void testUserAffiliation() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -2686,20 +2751,20 @@
 
         // Check that the system user is unaffiliated.
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
-        assertFalse(dpm.isAffiliatedUser());
+        assertThat(dpm.isAffiliatedUser()).isFalse();
 
         // Set a device owner on the system user. Check that the system user becomes affiliated.
         setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
         dpm.setActiveAdmin(admin1, /* replace =*/ false);
-        assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
-        assertTrue(dpm.isAffiliatedUser());
-        assertTrue(dpm.getAffiliationIds(admin1).isEmpty());
+        assertThat(dpm.setDeviceOwner(admin1, "owner-name")).isTrue();
+        assertThat(dpm.isAffiliatedUser()).isTrue();
+        assertThat(dpm.getAffiliationIds(admin1).isEmpty()).isTrue();
 
         // Install a profile owner. Check that the test user is unaffiliated.
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         setAsProfileOwner(admin2);
-        assertFalse(dpm.isAffiliatedUser());
-        assertTrue(dpm.getAffiliationIds(admin2).isEmpty());
+        assertThat(dpm.isAffiliatedUser()).isFalse();
+        assertThat(dpm.getAffiliationIds(admin2).isEmpty()).isTrue();
 
         // Have the profile owner specify a set of affiliation ids. Check that the test user remains
         // unaffiliated.
@@ -2709,7 +2774,7 @@
         userAffiliationIds.add("blue");
         dpm.setAffiliationIds(admin2, userAffiliationIds);
         MoreAsserts.assertContentsInAnyOrder(dpm.getAffiliationIds(admin2), "red", "green", "blue");
-        assertFalse(dpm.isAffiliatedUser());
+        assertThat(dpm.isAffiliatedUser()).isFalse();
 
         // Have the device owner specify a set of affiliation ids that do not intersect with those
         // specified by the profile owner. Check that the test user remains unaffiliated.
@@ -2722,7 +2787,7 @@
         MoreAsserts.assertContentsInAnyOrder(
             dpm.getAffiliationIds(admin1), "cyan", "yellow", "magenta");
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
-        assertFalse(dpm.isAffiliatedUser());
+        assertThat(dpm.isAffiliatedUser()).isFalse();
 
         // Have the profile owner specify a set of affiliation ids that intersect with those
         // specified by the device owner. Check that the test user becomes affiliated.
@@ -2730,33 +2795,36 @@
         dpm.setAffiliationIds(admin2, userAffiliationIds);
         MoreAsserts.assertContentsInAnyOrder(
             dpm.getAffiliationIds(admin2), "red", "green", "blue", "yellow");
-        assertTrue(dpm.isAffiliatedUser());
+        assertThat(dpm.isAffiliatedUser()).isTrue();
 
         // Clear affiliation ids for the profile owner. The user becomes unaffiliated.
         dpm.setAffiliationIds(admin2, Collections.emptySet());
-        assertTrue(dpm.getAffiliationIds(admin2).isEmpty());
-        assertFalse(dpm.isAffiliatedUser());
+        assertThat(dpm.getAffiliationIds(admin2).isEmpty()).isTrue();
+        assertThat(dpm.isAffiliatedUser()).isFalse();
 
         // Set affiliation ids again, then clear PO to check that the user becomes unaffiliated
         dpm.setAffiliationIds(admin2, userAffiliationIds);
-        assertTrue(dpm.isAffiliatedUser());
+        assertThat(dpm.isAffiliatedUser()).isTrue();
         dpm.clearProfileOwner(admin2);
-        assertFalse(dpm.isAffiliatedUser());
+        assertThat(dpm.isAffiliatedUser()).isFalse();
 
         // Check that the system user remains affiliated.
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
-        assertTrue(dpm.isAffiliatedUser());
+        assertThat(dpm.isAffiliatedUser()).isTrue();
 
         // Clear the device owner - the user becomes unaffiliated.
         clearDeviceOwner();
-        assertFalse(dpm.isAffiliatedUser());
+        assertThat(dpm.isAffiliatedUser()).isFalse();
     }
 
+    @Test
     public void testGetUserProvisioningState_defaultResult() {
         mContext.callerPermissions.add(permission.MANAGE_USERS);
-        assertEquals(DevicePolicyManager.STATE_USER_UNMANAGED, dpm.getUserProvisioningState());
+        assertThat(dpm.getUserProvisioningState())
+                .isEqualTo(DevicePolicyManager.STATE_USER_UNMANAGED);
     }
 
+    @Test
     public void testSetUserProvisioningState_permission() throws Exception {
         setupProfileOwner();
 
@@ -2764,6 +2832,7 @@
                 DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
     }
 
+    @Test
     public void testSetUserProvisioningState_unprivileged() throws Exception {
         setupProfileOwner();
         assertExpectException(SecurityException.class, /* messageRegex =*/ null,
@@ -2771,6 +2840,7 @@
                         CALLER_USER_HANDLE));
     }
 
+    @Test
     public void testSetUserProvisioningState_noManagement() {
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
         mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -2778,9 +2848,11 @@
                 /* messageRegex= */ "change provisioning state unless a .* owner is set",
                 () -> dpm.setUserProvisioningState(DevicePolicyManager.STATE_USER_SETUP_FINALIZED,
                         CALLER_USER_HANDLE));
-        assertEquals(DevicePolicyManager.STATE_USER_UNMANAGED, dpm.getUserProvisioningState());
+        assertThat(dpm.getUserProvisioningState())
+                .isEqualTo(DevicePolicyManager.STATE_USER_UNMANAGED);
     }
 
+    @Test
     public void testSetUserProvisioningState_deviceOwnerFromSetupWizard() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -2790,6 +2862,7 @@
                 DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
     }
 
+    @Test
     public void testSetUserProvisioningState_deviceOwnerFromSetupWizardAlternative()
             throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -2800,6 +2873,7 @@
                 DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
     }
 
+    @Test
     public void testSetUserProvisioningState_deviceOwnerWithoutSetupWizard() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -2808,6 +2882,7 @@
                 DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
     }
 
+    @Test
     public void testSetUserProvisioningState_managedProfileFromSetupWizard_primaryUser()
             throws Exception {
         setupProfileOwner();
@@ -2817,6 +2892,7 @@
                 DevicePolicyManager.STATE_USER_PROFILE_FINALIZED);
     }
 
+    @Test
     public void testSetUserProvisioningState_managedProfileFromSetupWizard_managedProfile()
             throws Exception {
         setupProfileOwner();
@@ -2826,6 +2902,7 @@
                 DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
     }
 
+    @Test
     public void testSetUserProvisioningState_managedProfileWithoutSetupWizard() throws Exception {
         setupProfileOwner();
 
@@ -2833,6 +2910,7 @@
                 DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
     }
 
+    @Test
     public void testSetUserProvisioningState_illegalTransitionOutOfFinalized1() throws Exception {
         setupProfileOwner();
 
@@ -2843,6 +2921,7 @@
                         DevicePolicyManager.STATE_USER_UNMANAGED));
     }
 
+    @Test
     public void testSetUserProvisioningState_illegalTransitionToAnotherInProgressState()
             throws Exception {
         setupProfileOwner();
@@ -2858,10 +2937,11 @@
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
         mContext.callerPermissions.add(permission.MANAGE_USERS);
 
-        assertEquals(DevicePolicyManager.STATE_USER_UNMANAGED, dpm.getUserProvisioningState());
+        assertThat(dpm.getUserProvisioningState())
+                .isEqualTo(DevicePolicyManager.STATE_USER_UNMANAGED);
         for (int state : states) {
             dpm.setUserProvisioningState(state, userId);
-            assertEquals(state, dpm.getUserProvisioningState());
+            assertThat(dpm.getUserProvisioningState()).isEqualTo(state);
         }
     }
 
@@ -2870,7 +2950,7 @@
 
         setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID);
         dpm.setActiveAdmin(admin1, false);
-        assertTrue(dpm.setProfileOwner(admin1, null, CALLER_USER_HANDLE));
+        assertThat(dpm.setProfileOwner(admin1, null, CALLER_USER_HANDLE)).isTrue();
 
         mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
     }
@@ -2880,7 +2960,7 @@
 
         setUpPackageManagerForAdmin(admin1, DpmMockContext.SYSTEM_UID);
         dpm.setActiveAdmin(admin1, false);
-        assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM));
+        assertThat(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
 
         mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
     }
@@ -2890,11 +2970,12 @@
 
         setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
         dpm.setActiveAdmin(admin1, false);
-        assertTrue(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM));
+        assertThat(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
 
         mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
     }
 
+    @Test
     public void testSetMaximumTimeToLock() {
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
 
@@ -2956,6 +3037,7 @@
         verifyStayOnWhilePluggedCleared(false);
     }
 
+    @Test
     public void testIsActiveSupervisionApp() throws Exception {
         when(mServiceContext.resources
                 .getString(R.string.config_defaultSupervisionProfileOwnerComponent))
@@ -2968,11 +3050,12 @@
 
         final DevicePolicyManagerInternal dpmi =
                 LocalServices.getService(DevicePolicyManagerInternal.class);
-        assertTrue(dpmi.isActiveSupervisionApp(PROFILE_ADMIN));
+        assertThat(dpmi.isActiveSupervisionApp(PROFILE_ADMIN)).isTrue();
     }
 
     // Test if lock timeout on managed profile is handled correctly depending on whether profile
     // uses separate challenge.
+    @Test
     public void testSetMaximumTimeToLockProfile() throws Exception {
         final int PROFILE_USER = 15;
         final int PROFILE_ADMIN = UserHandle.getUid(PROFILE_USER, 19436);
@@ -3039,6 +3122,7 @@
         verifyScreenTimeoutCall(Long.MAX_VALUE, UserHandle.USER_SYSTEM);
     }
 
+    @Test
     public void testSetRequiredStrongAuthTimeout_DeviceOwner() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -3055,8 +3139,8 @@
         getServices().buildMock.isDebuggable = false;
 
         dpm.setRequiredStrongAuthTimeout(admin1, MAX_MINUS_ONE_MINUTE);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MAX_MINUS_ONE_MINUTE);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(null), MAX_MINUS_ONE_MINUTE);
+        assertThat(MAX_MINUS_ONE_MINUTE).isEqualTo(dpm.getRequiredStrongAuthTimeout(admin1));
+        assertThat(MAX_MINUS_ONE_MINUTE).isEqualTo(dpm.getRequiredStrongAuthTimeout(null));
 
         verify(getServices().systemProperties, never()).getLong(anyString(), anyLong());
 
@@ -3067,45 +3151,47 @@
         dpm.setRequiredStrongAuthTimeout(admin1, 0);
 
         // aggregation should be the default if unset by any admin
-        assertEquals(dpm.getRequiredStrongAuthTimeout(null),
-                DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+        assertThat(DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS)
+                .isEqualTo(dpm.getRequiredStrongAuthTimeout(null));
 
         // admin not participating by default
-        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
+        assertThat(dpm.getRequiredStrongAuthTimeout(admin1)).isEqualTo(0);
 
         //clamping from the top
         dpm.setRequiredStrongAuthTimeout(admin1,
                 DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS + ONE_MINUTE);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1),
-                DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(null),
-                DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+        assertThat(DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS)
+                .isEqualTo(dpm.getRequiredStrongAuthTimeout(admin1));
+        assertThat(DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS)
+                .isEqualTo(dpm.getRequiredStrongAuthTimeout(null));
 
         // 0 means the admin is not participating, so default should be returned
         dpm.setRequiredStrongAuthTimeout(admin1, 0);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(null),
-                DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+        assertThat(dpm.getRequiredStrongAuthTimeout(admin1)).isEqualTo(0);
+        assertThat(DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS)
+                .isEqualTo(dpm.getRequiredStrongAuthTimeout(null));
 
         // clamping from the bottom
         dpm.setRequiredStrongAuthTimeout(admin1, MINIMUM_STRONG_AUTH_TIMEOUT_MS - ONE_MINUTE);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MINIMUM_STRONG_AUTH_TIMEOUT_MS);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(null), MINIMUM_STRONG_AUTH_TIMEOUT_MS);
+        assertThat(dpm.getRequiredStrongAuthTimeout(admin1))
+                .isEqualTo(MINIMUM_STRONG_AUTH_TIMEOUT_MS);
+        assertThat(dpm.getRequiredStrongAuthTimeout(null))
+                .isEqualTo(MINIMUM_STRONG_AUTH_TIMEOUT_MS);
 
         // values within range
         dpm.setRequiredStrongAuthTimeout(admin1, MIN_PLUS_ONE_MINUTE);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MIN_PLUS_ONE_MINUTE);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(null), MIN_PLUS_ONE_MINUTE);
+        assertThat(dpm.getRequiredStrongAuthTimeout(admin1)).isEqualTo(MIN_PLUS_ONE_MINUTE);
+        assertThat(dpm.getRequiredStrongAuthTimeout(null)).isEqualTo(MIN_PLUS_ONE_MINUTE);
 
         dpm.setRequiredStrongAuthTimeout(admin1, MAX_MINUS_ONE_MINUTE);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MAX_MINUS_ONE_MINUTE);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(null), MAX_MINUS_ONE_MINUTE);
+        assertThat(dpm.getRequiredStrongAuthTimeout(admin1)).isEqualTo(MAX_MINUS_ONE_MINUTE);
+        assertThat(dpm.getRequiredStrongAuthTimeout(null)).isEqualTo(MAX_MINUS_ONE_MINUTE);
 
         // reset to default
         dpm.setRequiredStrongAuthTimeout(admin1, 0);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
-        assertEquals(dpm.getRequiredStrongAuthTimeout(null),
-                DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+        assertThat(dpm.getRequiredStrongAuthTimeout(admin1)).isEqualTo(0);
+        assertThat(DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS)
+                .isEqualTo(dpm.getRequiredStrongAuthTimeout(null));
 
         // negative value
         assertExpectException(IllegalArgumentException.class, /* messageRegex= */ null,
@@ -3130,8 +3216,8 @@
     private void setup_DeviceAdminFeatureOff() throws Exception {
         when(getServices().packageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN))
                 .thenReturn(false);
-        when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
-                .thenReturn(false);
+        when(getServices().ipackageManager
+                .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(false);
         initializeDpms();
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(false);
         when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
@@ -3141,6 +3227,7 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
     }
 
+    @Test
     public void testIsProvisioningAllowed_DeviceAdminFeatureOff() throws Exception {
         setup_DeviceAdminFeatureOff();
         mContext.packageName = admin1.getPackageName();
@@ -3153,6 +3240,7 @@
         assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, false);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_DeviceAdminFeatureOff() throws Exception {
         setup_DeviceAdminFeatureOff();
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -3170,8 +3258,8 @@
     }
 
     private void setup_ManagedProfileFeatureOff() throws Exception {
-        when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
-                .thenReturn(false);
+        when(getServices().ipackageManager
+                .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(false);
         initializeDpms();
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(false);
         when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
@@ -3181,6 +3269,7 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
     }
 
+    @Test
     public void testIsProvisioningAllowed_ManagedProfileFeatureOff() throws Exception {
         setup_ManagedProfileFeatureOff();
         mContext.packageName = admin1.getPackageName();
@@ -3202,6 +3291,7 @@
         assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, false);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_ManagedProfileFeatureOff() throws Exception {
         setup_ManagedProfileFeatureOff();
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -3233,8 +3323,8 @@
     }
 
     private void setup_nonSplitUser_firstBoot_primaryUser() throws Exception {
-        when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
-                .thenReturn(true);
+        when(getServices().ipackageManager
+                .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(false);
         when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
                 .thenReturn(true);
@@ -3244,6 +3334,7 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
     }
 
+    @Test
     public void testIsProvisioningAllowed_nonSplitUser_firstBoot_primaryUser() throws Exception {
         setup_nonSplitUser_firstBoot_primaryUser();
         mContext.packageName = admin1.getPackageName();
@@ -3257,6 +3348,7 @@
                 false /* because of non-split user */);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_nonSplitUser_firstBoot_primaryUser()
             throws Exception {
         setup_nonSplitUser_firstBoot_primaryUser();
@@ -3275,8 +3367,8 @@
     }
 
     private void setup_nonSplitUser_afterDeviceSetup_primaryUser() throws Exception {
-        when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
-                .thenReturn(true);
+        when(getServices().ipackageManager
+                .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(false);
         when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
                 .thenReturn(true);
@@ -3302,6 +3394,7 @@
                 true)).thenReturn(true);
     }
 
+    @Test
     public void testIsProvisioningAllowed_nonSplitUser_afterDeviceSetup_primaryUser()
             throws Exception {
         setup_nonSplitUser_afterDeviceSetup_primaryUser();
@@ -3318,6 +3411,7 @@
                 false/* because of non-split user */);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_nonSplitUser_afterDeviceSetup_primaryUser()
             throws Exception {
         setup_nonSplitUser_afterDeviceSetup_primaryUser();
@@ -3335,6 +3429,7 @@
                 DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
     }
 
+    @Test
     public void testProvisioning_nonSplitUser_withDo_primaryUser() throws Exception {
         setup_nonSplitUser_withDo_primaryUser();
         mContext.packageName = admin1.getPackageName();
@@ -3361,6 +3456,7 @@
                 DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
     }
 
+    @Test
     public void testProvisioning_nonSplitUser_withDo_primaryUser_restrictedBySystem()
             throws Exception {
         setup_nonSplitUser_withDo_primaryUser();
@@ -3388,6 +3484,7 @@
                 DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
     }
 
+    @Test
     public void testCheckCannotSetProfileOwnerWithDeviceOwner() throws Exception {
         setup_nonSplitUser_withDo_primaryUser();
         final int managedProfileUserId = 18;
@@ -3399,10 +3496,11 @@
         mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
         setUpPackageManagerForFakeAdmin(admin1, managedProfileAdminUid, admin1);
         dpm.setActiveAdmin(admin1, false, userId);
-        assertFalse(dpm.setProfileOwner(admin1, null, userId));
+        assertThat(dpm.setProfileOwner(admin1, null, userId)).isFalse();
         mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_nonSplitUser_attemptingComp() throws Exception {
         setup_nonSplitUser_withDo_primaryUser_ManagedProfile();
         mContext.packageName = admin1.getPackageName();
@@ -3420,6 +3518,7 @@
                 DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_nonSplitUser_comp_cannot_remove_profile()
             throws Exception {
         setup_nonSplitUser_withDo_primaryUser_ManagedProfile();
@@ -3449,8 +3548,8 @@
     }
 
     private void setup_splitUser_firstBoot_systemUser() throws Exception {
-        when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
-                .thenReturn(true);
+        when(getServices().ipackageManager
+                .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
         when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
                 .thenReturn(false);
@@ -3459,6 +3558,7 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
     }
 
+    @Test
     public void testIsProvisioningAllowed_splitUser_firstBoot_systemUser() throws Exception {
         setup_splitUser_firstBoot_systemUser();
         mContext.packageName = admin1.getPackageName();
@@ -3473,6 +3573,7 @@
                 false/* because calling uid is system user */);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_splitUser_firstBoot_systemUser()
             throws Exception {
         setup_splitUser_firstBoot_systemUser();
@@ -3491,8 +3592,8 @@
     }
 
     private void setup_splitUser_afterDeviceSetup_systemUser() throws Exception {
-        when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
-                .thenReturn(true);
+        when(getServices().ipackageManager
+                .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
         when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
                 .thenReturn(false);
@@ -3501,6 +3602,7 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
     }
 
+    @Test
     public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_systemUser() throws Exception {
         setup_splitUser_afterDeviceSetup_systemUser();
         mContext.packageName = admin1.getPackageName();
@@ -3517,6 +3619,7 @@
                 false/* because calling uid is system user */);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_splitUser_afterDeviceSetup_systemUser()
             throws Exception {
         setup_splitUser_afterDeviceSetup_systemUser();
@@ -3535,8 +3638,8 @@
     }
 
     private void setup_splitUser_firstBoot_primaryUser() throws Exception {
-        when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
-                .thenReturn(true);
+        when(getServices().ipackageManager
+                .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
         when(getServices().userManager.canAddMoreManagedProfiles(CALLER_USER_HANDLE,
                 true)).thenReturn(true);
@@ -3545,6 +3648,7 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
     }
 
+    @Test
     public void testIsProvisioningAllowed_splitUser_firstBoot_primaryUser() throws Exception {
         setup_splitUser_firstBoot_primaryUser();
         mContext.packageName = admin1.getPackageName();
@@ -3557,6 +3661,7 @@
         assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, true);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_splitUser_firstBoot_primaryUser()
             throws Exception {
         setup_splitUser_firstBoot_primaryUser();
@@ -3575,8 +3680,8 @@
     }
 
     private void setup_splitUser_afterDeviceSetup_primaryUser() throws Exception {
-        when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
-                .thenReturn(true);
+        when(getServices().ipackageManager
+                .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
         when(getServices().userManager.canAddMoreManagedProfiles(CALLER_USER_HANDLE,
                 true)).thenReturn(true);
@@ -3585,6 +3690,7 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
     }
 
+    @Test
     public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_primaryUser()
             throws Exception {
         setup_splitUser_afterDeviceSetup_primaryUser();
@@ -3601,6 +3707,7 @@
                 false/* because user setup completed */);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_splitUser_afterDeviceSetup_primaryUser()
             throws Exception {
         setup_splitUser_afterDeviceSetup_primaryUser();
@@ -3621,8 +3728,8 @@
     private void setup_provisionManagedProfileWithDeviceOwner_systemUser() throws Exception {
         setDeviceOwner();
 
-        when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
-                .thenReturn(true);
+        when(getServices().ipackageManager
+                .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
         when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
                 .thenReturn(false);
@@ -3631,6 +3738,7 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
     }
 
+    @Test
     public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_systemUser()
             throws Exception {
         setup_provisionManagedProfileWithDeviceOwner_systemUser();
@@ -3640,6 +3748,7 @@
                 false /* can't provision managed profile on system user */);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_systemUser()
             throws Exception {
         setup_provisionManagedProfileWithDeviceOwner_systemUser();
@@ -3651,8 +3760,8 @@
     private void setup_provisionManagedProfileWithDeviceOwner_primaryUser() throws Exception {
         setDeviceOwner();
 
-        when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
-                .thenReturn(true);
+        when(getServices().ipackageManager
+                .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(false);
         when(getServices().userManager.getProfileParent(CALLER_USER_HANDLE))
             .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0));
@@ -3663,6 +3772,7 @@
         mContext.binder.callingUid = DpmMockContext.ANOTHER_UID;
     }
 
+    @Test
     public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_primaryUser()
             throws Exception {
         setup_provisionManagedProfileWithDeviceOwner_primaryUser();
@@ -3671,6 +3781,7 @@
         assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_primaryUser()
             throws Exception {
         setup_provisionManagedProfileWithDeviceOwner_primaryUser();
@@ -3684,8 +3795,8 @@
     private void setup_provisionManagedProfileCantRemoveUser_primaryUser() throws Exception {
         setDeviceOwner();
 
-        when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
-                .thenReturn(true);
+        when(getServices().ipackageManager
+                .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
         when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
         when(getServices().userManager.hasUserRestriction(
                 eq(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE),
@@ -3700,6 +3811,7 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
     }
 
+    @Test
     public void testIsProvisioningAllowed_provisionManagedProfileCantRemoveUser_primaryUser()
             throws Exception {
         setup_provisionManagedProfileCantRemoveUser_primaryUser();
@@ -3708,6 +3820,7 @@
         assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_provisionManagedProfileCantRemoveUser_primaryUser()
             throws Exception {
         setup_provisionManagedProfileCantRemoveUser_primaryUser();
@@ -3716,6 +3829,7 @@
                 DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
     }
 
+    @Test
     public void testCheckProvisioningPreCondition_permission() {
         // GIVEN the permission MANAGE_PROFILE_AND_DEVICE_OWNERS is not granted
         assertExpectException(SecurityException.class, /* messageRegex =*/ null,
@@ -3723,12 +3837,14 @@
                         DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, "some.package"));
     }
 
+    @Test
     public void testForceUpdateUserSetupComplete_permission() {
         // GIVEN the permission MANAGE_PROFILE_AND_DEVICE_OWNERS is not granted
         assertExpectException(SecurityException.class, /* messageRegex =*/ null,
                 () -> dpm.forceUpdateUserSetupComplete());
     }
 
+    @Test
     public void testForceUpdateUserSetupComplete_systemUser() {
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
         // GIVEN calling from user 20
@@ -3737,6 +3853,7 @@
                 () -> dpm.forceUpdateUserSetupComplete());
     }
 
+    @Test
     public void testForceUpdateUserSetupComplete_userbuild() {
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -3753,14 +3870,15 @@
         // GIVEN it's user build
         getServices().buildMock.isDebuggable = false;
 
-        assertTrue(dpms.hasUserSetupCompleted());
+        assertThat(dpms.hasUserSetupCompleted()).isTrue();
 
         dpm.forceUpdateUserSetupComplete();
 
         // THEN the state in dpms is not changed
-        assertTrue(dpms.hasUserSetupCompleted());
+        assertThat(dpms.hasUserSetupCompleted()).isTrue();
     }
 
+    @Test
     public void testForceUpdateUserSetupComplete_userDebugbuild() {
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -3777,12 +3895,12 @@
         // GIVEN it's userdebug build
         getServices().buildMock.isDebuggable = true;
 
-        assertTrue(dpms.hasUserSetupCompleted());
+        assertThat(dpms.hasUserSetupCompleted()).isTrue();
 
         dpm.forceUpdateUserSetupComplete();
 
         // THEN the state in dpms is not changed
-        assertFalse(dpms.hasUserSetupCompleted());
+        assertThat(dpms.hasUserSetupCompleted()).isFalse();
     }
 
     private void clearDeviceOwner() throws Exception {
@@ -3795,6 +3913,7 @@
         });
     }
 
+    @Test
     public void testGetLastSecurityLogRetrievalTime() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -3806,7 +3925,7 @@
                 .thenReturn(true);
 
         // No logs were retrieved so far.
-        assertEquals(-1, dpm.getLastSecurityLogRetrievalTime());
+        assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(-1);
 
         // Enabling logging should not change the timestamp.
         dpm.setSecurityLoggingEnabled(admin1, true);
@@ -3814,55 +3933,56 @@
                 .securityLogSetLoggingEnabledProperty(true);
         when(getServices().settings.securityLogGetLoggingEnabledProperty())
                 .thenReturn(true);
-        assertEquals(-1, dpm.getLastSecurityLogRetrievalTime());
+        assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(-1);
 
         // Retrieving the logs should update the timestamp.
         final long beforeRetrieval = System.currentTimeMillis();
         dpm.retrieveSecurityLogs(admin1);
         final long firstSecurityLogRetrievalTime = dpm.getLastSecurityLogRetrievalTime();
         final long afterRetrieval = System.currentTimeMillis();
-        assertTrue(firstSecurityLogRetrievalTime >= beforeRetrieval);
-        assertTrue(firstSecurityLogRetrievalTime <= afterRetrieval);
+        assertThat(firstSecurityLogRetrievalTime >= beforeRetrieval).isTrue();
+        assertThat(firstSecurityLogRetrievalTime <= afterRetrieval).isTrue();
 
         // Retrieving the pre-boot logs should update the timestamp.
         Thread.sleep(2);
         dpm.retrievePreRebootSecurityLogs(admin1);
         final long secondSecurityLogRetrievalTime = dpm.getLastSecurityLogRetrievalTime();
-        assertTrue(secondSecurityLogRetrievalTime > firstSecurityLogRetrievalTime);
+        assertThat(secondSecurityLogRetrievalTime > firstSecurityLogRetrievalTime).isTrue();
 
         // Checking the timestamp again should not change it.
         Thread.sleep(2);
-        assertEquals(secondSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
+        assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(secondSecurityLogRetrievalTime);
 
         // Retrieving the logs again should update the timestamp.
         dpm.retrieveSecurityLogs(admin1);
         final long thirdSecurityLogRetrievalTime = dpm.getLastSecurityLogRetrievalTime();
-        assertTrue(thirdSecurityLogRetrievalTime > secondSecurityLogRetrievalTime);
+        assertThat(thirdSecurityLogRetrievalTime > secondSecurityLogRetrievalTime).isTrue();
 
         // Disabling logging should not change the timestamp.
         Thread.sleep(2);
         dpm.setSecurityLoggingEnabled(admin1, false);
-        assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
+        assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(thirdSecurityLogRetrievalTime);
 
         // Restarting the DPMS should not lose the timestamp.
         initializeDpms();
-        assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
+        assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(thirdSecurityLogRetrievalTime);
 
         // Any uid holding MANAGE_USERS permission can retrieve the timestamp.
         mContext.binder.callingUid = 1234567;
         mContext.callerPermissions.add(permission.MANAGE_USERS);
-        assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
+        assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(thirdSecurityLogRetrievalTime);
         mContext.callerPermissions.remove(permission.MANAGE_USERS);
 
         // System can retrieve the timestamp.
         mContext.binder.clearCallingIdentity();
-        assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
+        assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(thirdSecurityLogRetrievalTime);
 
         // Removing the device owner should clear the timestamp.
         clearDeviceOwner();
-        assertEquals(-1, dpm.getLastSecurityLogRetrievalTime());
+        assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(-1);
     }
 
+    @Test
     public void testSetConfiguredNetworksLockdownStateWithDO() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -3875,6 +3995,7 @@
                 Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0);
     }
 
+    @Test
     public void testSetConfiguredNetworksLockdownStateWithPO() throws Exception {
         setupProfileOwner();
         assertExpectException(SecurityException.class, null,
@@ -3883,6 +4004,7 @@
                 Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0);
     }
 
+    @Test
     public void testSetConfiguredNetworksLockdownStateWithPOOfOrganizationOwnedDevice()
             throws Exception {
         setupProfileOwner();
@@ -3896,6 +4018,7 @@
                 Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0);
     }
 
+    @Test
     public void testSetSystemSettingFailWithNonWhitelistedSettings() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -3903,6 +4026,7 @@
                 dpm.setSystemSetting(admin1, Settings.System.SCREEN_BRIGHTNESS_FOR_VR, "0"));
     }
 
+    @Test
     public void testSetSystemSettingWithDO() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -3911,6 +4035,7 @@
                 Settings.System.SCREEN_BRIGHTNESS, "0", UserHandle.USER_SYSTEM);
     }
 
+    @Test
     public void testSetSystemSettingWithPO() throws Exception {
         setupProfileOwner();
         dpm.setSystemSetting(admin1, Settings.System.SCREEN_BRIGHTNESS, "0");
@@ -3918,6 +4043,7 @@
             Settings.System.SCREEN_BRIGHTNESS, "0", CALLER_USER_HANDLE);
     }
 
+    @Test
     public void testSetAutoTimeEnabledModifiesSetting() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -3928,6 +4054,7 @@
         verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
     }
 
+    @Test
     public void testSetAutoTimeEnabledWithPOOnUser0() throws Exception {
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
         setupProfileOwnerOnUser0();
@@ -3938,6 +4065,7 @@
         verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
     }
 
+    @Test
     public void testSetAutoTimeEnabledFailWithPONotOnUser0() throws Exception {
         setupProfileOwner();
         assertExpectException(SecurityException.class, null,
@@ -3945,6 +4073,7 @@
         verify(getServices().settings, never()).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
     }
 
+    @Test
     public void testSetAutoTimeEnabledWithPOOfOrganizationOwnedDevice() throws Exception {
         setupProfileOwner();
         configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
@@ -3956,6 +4085,7 @@
         verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
     }
 
+    @Test
     public void testSetAutoTimeZoneEnabledModifiesSetting() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -3966,6 +4096,7 @@
         verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
     }
 
+    @Test
     public void testSetAutoTimeZoneEnabledWithPOOnUser0() throws Exception {
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
         setupProfileOwnerOnUser0();
@@ -3976,6 +4107,7 @@
         verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
     }
 
+    @Test
     public void testSetAutoTimeZoneEnabledFailWithPONotOnUser0() throws Exception {
         setupProfileOwner();
         assertExpectException(SecurityException.class, null,
@@ -3984,6 +4116,7 @@
                 0);
     }
 
+    @Test
     public void testSetAutoTimeZoneEnabledWithPOOfOrganizationOwnedDevice() throws Exception {
         setupProfileOwner();
         configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
@@ -3995,12 +4128,13 @@
         verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
     }
 
+    @Test
     public void testIsOrganizationOwnedDevice() throws Exception {
         // Set up the user manager to return correct user info
         addManagedProfile(admin1, DpmMockContext.CALLER_UID, admin1);
 
         // Any caller should be able to call this method.
-        assertFalse(dpm.isOrganizationOwnedDeviceWithManagedProfile());
+        assertThat(dpm.isOrganizationOwnedDeviceWithManagedProfile()).isFalse();
         configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
 
         verify(getServices().userManager).setUserRestriction(
@@ -4008,13 +4142,14 @@
                 eq(true),
                 eq(UserHandle.of(UserHandle.USER_SYSTEM)));
 
-        assertTrue(dpm.isOrganizationOwnedDeviceWithManagedProfile());
+        assertThat(dpm.isOrganizationOwnedDeviceWithManagedProfile()).isTrue();
 
         // A random caller from another user should also be able to get the right result.
         mContext.binder.callingUid = DpmMockContext.ANOTHER_UID;
-        assertTrue(dpm.isOrganizationOwnedDeviceWithManagedProfile());
+        assertThat(dpm.isOrganizationOwnedDeviceWithManagedProfile()).isTrue();
     }
 
+    @Test
     public void testMarkOrganizationOwnedDevice_baseRestrictionsAdded() throws Exception {
         addManagedProfile(admin1, DpmMockContext.CALLER_UID, admin1);
 
@@ -4044,6 +4179,7 @@
                 parentDpm.clearUserRestriction(admin1, UserManager.DISALLOW_ADD_USER));
     }
 
+    @Test
     public void testSetTime() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -4051,11 +4187,13 @@
         verify(getServices().alarmManager).setTime(0);
     }
 
+    @Test
     public void testSetTimeFailWithPO() throws Exception {
         setupProfileOwner();
         assertExpectException(SecurityException.class, null, () -> dpm.setTime(admin1, 0));
     }
 
+    @Test
     public void testSetTimeWithPOOfOrganizationOwnedDevice() throws Exception {
         setupProfileOwner();
         configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
@@ -4063,14 +4201,16 @@
         verify(getServices().alarmManager).setTime(0);
     }
 
+    @Test
     public void testSetTimeWithAutoTimeOn() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
         when(getServices().settings.settingsGlobalGetInt(Settings.Global.AUTO_TIME, 0))
                 .thenReturn(1);
-        assertFalse(dpm.setTime(admin1, 0));
+        assertThat(dpm.setTime(admin1, 0)).isFalse();
     }
 
+    @Test
     public void testSetTimeZone() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -4078,12 +4218,14 @@
         verify(getServices().alarmManager).setTimeZone("Asia/Shanghai");
     }
 
+    @Test
     public void testSetTimeZoneFailWithPO() throws Exception {
         setupProfileOwner();
         assertExpectException(SecurityException.class, null,
                 () -> dpm.setTimeZone(admin1, "Asia/Shanghai"));
     }
 
+    @Test
     public void testSetTimeZoneWithPOOfOrganizationOwnedDevice() throws Exception {
         setupProfileOwner();
         configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
@@ -4091,14 +4233,16 @@
         verify(getServices().alarmManager).setTimeZone("Asia/Shanghai");
     }
 
+    @Test
     public void testSetTimeZoneWithAutoTimeZoneOn() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
         when(getServices().settings.settingsGlobalGetInt(Settings.Global.AUTO_TIME_ZONE, 0))
                 .thenReturn(1);
-        assertFalse(dpm.setTimeZone(admin1, "Asia/Shanghai"));
+        assertThat(dpm.setTimeZone(admin1, "Asia/Shanghai")).isFalse();
     }
 
+    @Test
     public void testGetLastBugReportRequestTime() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -4115,39 +4259,40 @@
         getServices().removeUser(CALLER_USER_HANDLE);
 
         // No bug reports were requested so far.
-        assertEquals(-1, dpm.getLastBugReportRequestTime());
+        assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(-1);
 
         // Requesting a bug report should update the timestamp.
         final long beforeRequest = System.currentTimeMillis();
         dpm.requestBugreport(admin1);
         final long bugReportRequestTime = dpm.getLastBugReportRequestTime();
         final long afterRequest = System.currentTimeMillis();
-        assertTrue(bugReportRequestTime >= beforeRequest);
-        assertTrue(bugReportRequestTime <= afterRequest);
+        assertThat(bugReportRequestTime).isAtLeast(beforeRequest);
+        assertThat(bugReportRequestTime).isAtMost(afterRequest);
 
         // Checking the timestamp again should not change it.
         Thread.sleep(2);
-        assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());
+        assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(bugReportRequestTime);
 
         // Restarting the DPMS should not lose the timestamp.
         initializeDpms();
-        assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());
+        assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(bugReportRequestTime);
 
         // Any uid holding MANAGE_USERS permission can retrieve the timestamp.
         mContext.binder.callingUid = 1234567;
         mContext.callerPermissions.add(permission.MANAGE_USERS);
-        assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());
+        assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(bugReportRequestTime);
         mContext.callerPermissions.remove(permission.MANAGE_USERS);
 
         // System can retrieve the timestamp.
         mContext.binder.clearCallingIdentity();
-        assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());
+        assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(bugReportRequestTime);
 
         // Removing the device owner should clear the timestamp.
         clearDeviceOwner();
-        assertEquals(-1, dpm.getLastBugReportRequestTime());
+        assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(-1);
     }
 
+    @Test
     public void testGetLastNetworkLogRetrievalTime() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -4165,57 +4310,58 @@
                 .thenReturn(true);
 
         // No logs were retrieved so far.
-        assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());
+        assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1);
 
         // Attempting to retrieve logs without enabling logging should not change the timestamp.
         dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
-        assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());
+        assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1);
 
         // Enabling logging should not change the timestamp.
         dpm.setNetworkLoggingEnabled(admin1, true);
-        assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());
+        assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1);
 
         // Retrieving the logs should update the timestamp.
         final long beforeRetrieval = System.currentTimeMillis();
         dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
         final long firstNetworkLogRetrievalTime = dpm.getLastNetworkLogRetrievalTime();
         final long afterRetrieval = System.currentTimeMillis();
-        assertTrue(firstNetworkLogRetrievalTime >= beforeRetrieval);
-        assertTrue(firstNetworkLogRetrievalTime <= afterRetrieval);
+        assertThat(firstNetworkLogRetrievalTime >= beforeRetrieval).isTrue();
+        assertThat(firstNetworkLogRetrievalTime <= afterRetrieval).isTrue();
 
         // Checking the timestamp again should not change it.
         Thread.sleep(2);
-        assertEquals(firstNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());
+        assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(firstNetworkLogRetrievalTime);
 
         // Retrieving the logs again should update the timestamp.
         dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
         final long secondNetworkLogRetrievalTime = dpm.getLastNetworkLogRetrievalTime();
-        assertTrue(secondNetworkLogRetrievalTime > firstNetworkLogRetrievalTime);
+        assertThat(secondNetworkLogRetrievalTime > firstNetworkLogRetrievalTime).isTrue();
 
         // Disabling logging should not change the timestamp.
         Thread.sleep(2);
         dpm.setNetworkLoggingEnabled(admin1, false);
-        assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());
+        assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(secondNetworkLogRetrievalTime);
 
         // Restarting the DPMS should not lose the timestamp.
         initializeDpms();
-        assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());
+        assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(secondNetworkLogRetrievalTime);
 
         // Any uid holding MANAGE_USERS permission can retrieve the timestamp.
         mContext.binder.callingUid = 1234567;
         mContext.callerPermissions.add(permission.MANAGE_USERS);
-        assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());
+        assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(secondNetworkLogRetrievalTime);
         mContext.callerPermissions.remove(permission.MANAGE_USERS);
 
         // System can retrieve the timestamp.
         mContext.binder.clearCallingIdentity();
-        assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());
+        assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(secondNetworkLogRetrievalTime);
 
         // Removing the device owner should clear the timestamp.
         clearDeviceOwner();
-        assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());
+        assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1);
     }
 
+    @Test
     public void testGetBindDeviceAdminTargetUsers() throws Exception {
         // Setup device owner.
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -4268,9 +4414,9 @@
         dpm.setLockTaskPackages(who, packages);
         MoreAsserts.assertEquals(packages, dpm.getLockTaskPackages(who));
         for (String p : packages) {
-            assertTrue(dpm.isLockTaskPermitted(p));
+            assertThat(dpm.isLockTaskPermitted(p)).isTrue();
         }
-        assertFalse(dpm.isLockTaskPermitted("anotherPackage"));
+        assertThat(dpm.isLockTaskPermitted("anotherPackage")).isFalse();
         // Test to see if set lock task features can be set
         dpm.setLockTaskFeatures(who, flags);
         verifyLockTaskState(userId, packages, flags);
@@ -4283,11 +4429,12 @@
                 () -> dpm.setLockTaskPackages(who, packages));
         assertExpectException(SecurityException.class, /* messageRegex =*/ null,
                 () -> dpm.getLockTaskPackages(who));
-        assertFalse(dpm.isLockTaskPermitted("doPackage1"));
+        assertThat(dpm.isLockTaskPermitted("doPackage1")).isFalse();
         assertExpectException(SecurityException.class, /* messageRegex =*/ null,
                 () -> dpm.setLockTaskFeatures(who, flags));
     }
 
+    @Test
     public void testLockTaskPolicyForProfileOwner() throws Exception {
         // Setup a PO
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
@@ -4315,9 +4462,11 @@
         final int mpoFlags = DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS
                 | DevicePolicyManager.LOCK_TASK_FEATURE_HOME
                 | DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
-        verifyCanNotSetLockTask(MANAGED_PROFILE_ADMIN_UID, adminDifferentPackage, mpoPackages, mpoFlags);
+        verifyCanNotSetLockTask(MANAGED_PROFILE_ADMIN_UID, adminDifferentPackage, mpoPackages,
+                mpoFlags);
     }
 
+    @Test
     public void testLockTaskFeatures_IllegalArgumentException() throws Exception {
         // Setup a device owner.
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -4332,12 +4481,13 @@
                 () -> dpm.setLockTaskFeatures(admin1, flags));
     }
 
+    @Test
     public void testSecondaryLockscreen_profileOwner() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
 
         // Initial state is disabled.
-        assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
-                CALLER_USER_HANDLE)));
+        assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
+        CALLER_USER_HANDLE))).isFalse();
 
         // Profile owner can set enabled state.
         setAsProfileOwner(admin1);
@@ -4345,8 +4495,8 @@
                 .getString(R.string.config_defaultSupervisionProfileOwnerComponent))
                 .thenReturn(admin1.flattenToString());
         dpm.setSecondaryLockscreenEnabled(admin1, true);
-        assertTrue(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
-                CALLER_USER_HANDLE)));
+        assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
+        CALLER_USER_HANDLE))).isTrue();
 
         // Managed profile managed by different package is unaffiliated - cannot set enabled.
         final int managedProfileUserId = 15;
@@ -4359,11 +4509,13 @@
                 () -> dpm.setSecondaryLockscreenEnabled(adminDifferentPackage, false));
     }
 
+    @Test
     public void testSecondaryLockscreen_deviceOwner() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
 
         // Initial state is disabled.
-        assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(UserHandle.USER_SYSTEM)));
+        assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(UserHandle.USER_SYSTEM)))
+                .isFalse();
 
         // Device owners can set enabled state.
         setupDeviceOwner();
@@ -4371,14 +4523,16 @@
                 .getString(R.string.config_defaultSupervisionProfileOwnerComponent))
                 .thenReturn(admin1.flattenToString());
         dpm.setSecondaryLockscreenEnabled(admin1, true);
-        assertTrue(dpm.isSecondaryLockscreenEnabled(UserHandle.of(UserHandle.USER_SYSTEM)));
+        assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(UserHandle.USER_SYSTEM)))
+                .isTrue();
     }
 
+    @Test
     public void testSecondaryLockscreen_nonOwner() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
 
         // Initial state is disabled.
-        assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE)));
+        assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE))).isFalse();
 
         // Non-DO/PO cannot set enabled state.
         when(mServiceContext.resources
@@ -4386,9 +4540,10 @@
                 .thenReturn(admin1.flattenToString());
         assertExpectException(SecurityException.class, /* messageRegex= */ null,
                 () -> dpm.setSecondaryLockscreenEnabled(admin1, true));
-        assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE)));
+        assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE))).isFalse();
     }
 
+    @Test
     public void testSecondaryLockscreen_nonSupervisionApp() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
 
@@ -4403,13 +4558,13 @@
                 eq(CALLER_USER_HANDLE));
 
         // Initial state is disabled.
-        assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE)));
+        assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE))).isFalse();
 
         // Caller is Profile Owner, but no supervision app is configured.
         setAsProfileOwner(admin1);
         assertExpectException(SecurityException.class, "is not the default supervision component",
                 () -> dpm.setSecondaryLockscreenEnabled(admin1, true));
-        assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE)));
+        assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE))).isFalse();
 
         // Caller is Profile Owner, but is not the default configured supervision app.
         when(mServiceContext.resources
@@ -4417,22 +4572,23 @@
                 .thenReturn(admin2.flattenToString());
         assertExpectException(SecurityException.class, "is not the default supervision component",
                 () -> dpm.setSecondaryLockscreenEnabled(admin1, true));
-        assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE)));
+        assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE))).isFalse();
     }
 
+    @Test
     public void testIsDeviceManaged() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
 
         // The device owner itself, any uid holding MANAGE_USERS permission and the system can
         // find out that the device has a device owner.
-        assertTrue(dpm.isDeviceManaged());
+        assertThat(dpm.isDeviceManaged()).isTrue();
         mContext.binder.callingUid = 1234567;
         mContext.callerPermissions.add(permission.MANAGE_USERS);
-        assertTrue(dpm.isDeviceManaged());
+        assertThat(dpm.isDeviceManaged()).isTrue();
         mContext.callerPermissions.remove(permission.MANAGE_USERS);
         mContext.binder.clearCallingIdentity();
-        assertTrue(dpm.isDeviceManaged());
+        assertThat(dpm.isDeviceManaged()).isTrue();
 
         clearDeviceOwner();
 
@@ -4440,12 +4596,13 @@
         // not have a device owner.
         mContext.binder.callingUid = 1234567;
         mContext.callerPermissions.add(permission.MANAGE_USERS);
-        assertFalse(dpm.isDeviceManaged());
+        assertThat(dpm.isDeviceManaged()).isFalse();
         mContext.callerPermissions.remove(permission.MANAGE_USERS);
         mContext.binder.clearCallingIdentity();
-        assertFalse(dpm.isDeviceManaged());
+        assertThat(dpm.isDeviceManaged()).isFalse();
     }
 
+    @Test
     public void testDeviceOwnerOrganizationName() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -4453,23 +4610,24 @@
         dpm.setOrganizationName(admin1, "organization");
 
         // Device owner can retrieve organization managing the device.
-        assertEquals("organization", dpm.getDeviceOwnerOrganizationName());
+        assertThat(dpm.getDeviceOwnerOrganizationName()).isEqualTo("organization");
 
         // Any uid holding MANAGE_USERS permission can retrieve organization managing the device.
         mContext.binder.callingUid = 1234567;
         mContext.callerPermissions.add(permission.MANAGE_USERS);
-        assertEquals("organization", dpm.getDeviceOwnerOrganizationName());
+        assertThat(dpm.getDeviceOwnerOrganizationName()).isEqualTo("organization");
         mContext.callerPermissions.remove(permission.MANAGE_USERS);
 
         // System can retrieve organization managing the device.
         mContext.binder.clearCallingIdentity();
-        assertEquals("organization", dpm.getDeviceOwnerOrganizationName());
+        assertThat(dpm.getDeviceOwnerOrganizationName()).isEqualTo("organization");
 
         // Removing the device owner clears the organization managing the device.
         clearDeviceOwner();
-        assertNull(dpm.getDeviceOwnerOrganizationName());
+        assertThat(dpm.getDeviceOwnerOrganizationName()).isNull();
     }
 
+    @Test
     public void testWipeDataManagedProfile() throws Exception {
         final int MANAGED_PROFILE_USER_ID = 15;
         final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 19436);
@@ -4489,6 +4647,7 @@
                 MANAGED_PROFILE_USER_ID);
     }
 
+    @Test
     public void testWipeDataManagedProfileDisallowed() throws Exception {
         final int MANAGED_PROFILE_USER_ID = 15;
         final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 19436);
@@ -4512,6 +4671,7 @@
                 () -> dpm.wipeData(0));
     }
 
+    @Test
     public void testWipeDataDeviceOwner() throws Exception {
         setDeviceOwner();
         when(getServices().userManager.getUserRestrictionSource(
@@ -4527,6 +4687,7 @@
                 /*wipeEuicc=*/ eq(false));
     }
 
+    @Test
     public void testWipeEuiccDataEnabled() throws Exception {
         setDeviceOwner();
         when(getServices().userManager.getUserRestrictionSource(
@@ -4542,6 +4703,7 @@
                 /*wipeEuicc=*/ eq(true));
     }
 
+    @Test
     public void testWipeDataDeviceOwnerDisallowed() throws Exception {
         setDeviceOwner();
         when(getServices().userManager.getUserRestrictionSource(
@@ -4556,6 +4718,7 @@
                 () -> dpm.wipeData(0));
     }
 
+    @Test
     public void testMaximumFailedPasswordAttemptsReachedManagedProfile() throws Exception {
         final int MANAGED_PROFILE_USER_ID = 15;
         final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 19436);
@@ -4588,6 +4751,7 @@
         verifyZeroInteractions(getServices().recoverySystem);
     }
 
+    @Test
     public void testMaximumFailedPasswordAttemptsReachedManagedProfileDisallowed()
             throws Exception {
         final int MANAGED_PROFILE_USER_ID = 15;
@@ -4621,6 +4785,7 @@
         verifyZeroInteractions(getServices().recoverySystem);
     }
 
+    @Test
     public void testMaximumFailedPasswordAttemptsReachedDeviceOwner() throws Exception {
         setDeviceOwner();
         when(getServices().userManager.getUserRestrictionSource(
@@ -4643,6 +4808,7 @@
                 /*wipeEuicc=*/ eq(false));
     }
 
+    @Test
     public void testMaximumFailedPasswordAttemptsReachedDeviceOwnerDisallowed() throws Exception {
         setDeviceOwner();
         when(getServices().userManager.getUserRestrictionSource(
@@ -4664,6 +4830,7 @@
                 .removeUserEvenWhenDisallowed(anyInt());
     }
 
+    @Test
     public void testMaximumFailedDevicePasswordAttemptsReachedOrgOwnedManagedProfile()
             throws Exception {
         final int MANAGED_PROFILE_USER_ID = 15;
@@ -4679,16 +4846,16 @@
         mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
         dpm.setMaximumFailedPasswordsForWipe(admin1, 3);
 
-        assertEquals(3, dpm.getMaximumFailedPasswordsForWipe(admin1));
-        assertEquals(3, dpm.getMaximumFailedPasswordsForWipe(null));
+        assertThat(dpm.getMaximumFailedPasswordsForWipe(admin1)).isEqualTo(3);
+        assertThat(dpm.getMaximumFailedPasswordsForWipe(null)).isEqualTo(3);
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
         mContext.callerPermissions.add(permission.BIND_DEVICE_ADMIN);
 
-        assertEquals(3, dpm.getMaximumFailedPasswordsForWipe(null, UserHandle.USER_SYSTEM));
+        assertThat(dpm.getMaximumFailedPasswordsForWipe(null, UserHandle.USER_SYSTEM)).isEqualTo(3);
         // Check that primary will be wiped as a result of failed primary user unlock attempts.
-        assertEquals(UserHandle.USER_SYSTEM,
-                dpm.getProfileWithMinimumFailedPasswordsForWipe(UserHandle.USER_SYSTEM));
+        assertThat(dpm.getProfileWithMinimumFailedPasswordsForWipe(UserHandle.USER_SYSTEM))
+                .isEqualTo(UserHandle.USER_SYSTEM);
 
         // Failed password attempts on the parent user are taken into account, as there isn't a
         // separate work challenge.
@@ -4702,6 +4869,7 @@
                 /*wipeEuicc=*/ eq(false));
     }
 
+    @Test
     public void testMaximumFailedProfilePasswordAttemptsReachedOrgOwnedManagedProfile()
             throws Exception {
         final int MANAGED_PROFILE_USER_ID = 15;
@@ -4724,14 +4892,15 @@
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
         mContext.callerPermissions.add(permission.BIND_DEVICE_ADMIN);
 
-        assertEquals(0, dpm.getMaximumFailedPasswordsForWipe(null, UserHandle.USER_SYSTEM));
-        assertEquals(3, dpm.getMaximumFailedPasswordsForWipe(null, MANAGED_PROFILE_USER_ID));
+        assertThat(dpm.getMaximumFailedPasswordsForWipe(null, UserHandle.USER_SYSTEM)).isEqualTo(0);
+        assertThat(dpm.getMaximumFailedPasswordsForWipe(null, MANAGED_PROFILE_USER_ID))
+                .isEqualTo(3);
         // Check that the policy is not affecting primary profile challenge.
-        assertEquals(UserHandle.USER_NULL,
-                dpm.getProfileWithMinimumFailedPasswordsForWipe(UserHandle.USER_SYSTEM));
+        assertThat(dpm.getProfileWithMinimumFailedPasswordsForWipe(UserHandle.USER_SYSTEM))
+                .isEqualTo(UserHandle.USER_NULL);
         // Check that primary will be wiped as a result of failed profile unlock attempts.
-        assertEquals(UserHandle.USER_SYSTEM,
-                dpm.getProfileWithMinimumFailedPasswordsForWipe(MANAGED_PROFILE_USER_ID));
+        assertThat(dpm.getProfileWithMinimumFailedPasswordsForWipe(MANAGED_PROFILE_USER_ID))
+                .isEqualTo(UserHandle.USER_SYSTEM);
 
         // Simulate three failed attempts at solving the separate challenge.
         dpm.reportFailedPasswordAttempt(MANAGED_PROFILE_USER_ID);
@@ -4744,6 +4913,7 @@
                 /*wipeEuicc=*/ eq(false));
     }
 
+    @Test
     public void testGetPermissionGrantState() throws Exception {
         final String permission = "some.permission";
         final String app1 = "com.example.app1";
@@ -4766,10 +4936,10 @@
         // System can retrieve permission grant state.
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
         mContext.packageName = "android";
-        assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED,
-                dpm.getPermissionGrantState(null, app1, permission));
-        assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT,
-                dpm.getPermissionGrantState(null, app2, permission));
+        assertThat(dpm.getPermissionGrantState(null, app1, permission))
+                .isEqualTo(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
+        assertThat(dpm.getPermissionGrantState(null, app2, permission))
+                .isEqualTo(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
 
         // A regular app cannot retrieve permission grant state.
         mContext.binder.callingUid = setupPackageInPackageManager(app1, 1);
@@ -4781,12 +4951,13 @@
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         mContext.packageName = admin1.getPackageName();
         setAsProfileOwner(admin1);
-        assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED,
-                dpm.getPermissionGrantState(admin1, app1, permission));
-        assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT,
-                dpm.getPermissionGrantState(admin1, app2, permission));
+        assertThat(dpm.getPermissionGrantState(admin1, app1, permission))
+                .isEqualTo(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
+        assertThat(dpm.getPermissionGrantState(admin1, app2, permission))
+                .isEqualTo(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
     }
 
+    @Test
     public void testResetPasswordWithToken() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -4801,27 +4972,26 @@
         when(getServices().lockPatternUtils.addEscrowToken(eq(token), eq(UserHandle.USER_SYSTEM),
                 nullable(EscrowTokenStateChangeCallback.class)))
                 .thenReturn(handle);
-        assertTrue(dpm.setResetPasswordToken(admin1, token));
+        assertThat(dpm.setResetPasswordToken(admin1, token)).isTrue();
 
         // test password activation
-        when(getServices().lockPatternUtils.isEscrowTokenActive(eq(handle), eq(UserHandle.USER_SYSTEM)))
-            .thenReturn(true);
-        assertTrue(dpm.isResetPasswordTokenActive(admin1));
+        when(getServices().lockPatternUtils.isEscrowTokenActive(handle, UserHandle.USER_SYSTEM))
+                .thenReturn(true);
+        assertThat(dpm.isResetPasswordTokenActive(admin1)).isTrue();
 
         // test reset password with token
         when(getServices().lockPatternUtils.setLockCredentialWithToken(
-                eq(LockscreenCredential.createPassword(password)),
-                eq(handle), eq(token),
-                eq(UserHandle.USER_SYSTEM)))
-                .thenReturn(true);
-        assertTrue(dpm.resetPasswordWithToken(admin1, password, token, 0));
+                LockscreenCredential.createPassword(password), handle, token,
+                UserHandle.USER_SYSTEM)).thenReturn(true);
+        assertThat(dpm.resetPasswordWithToken(admin1, password, token, 0)).isTrue();
 
         // test removing a token
-        when(getServices().lockPatternUtils.removeEscrowToken(eq(handle), eq(UserHandle.USER_SYSTEM)))
+        when(getServices().lockPatternUtils.removeEscrowToken(handle, UserHandle.USER_SYSTEM))
                 .thenReturn(true);
-        assertTrue(dpm.clearResetPasswordToken(admin1));
+        assertThat(dpm.clearResetPasswordToken(admin1)).isTrue();
     }
 
+    @Test
     public void testIsActivePasswordSufficient() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         mContext.packageName = admin1.getPackageName();
@@ -4841,11 +5011,11 @@
         PasswordMetrics passwordMetricsNoSymbols = computeForPassword("abcdXYZ5".getBytes());
 
         setActivePasswordState(passwordMetricsNoSymbols);
-        assertTrue(dpm.isActivePasswordSufficient());
+        assertThat(dpm.isActivePasswordSufficient()).isTrue();
 
         initializeDpms();
         reset(mContext.spiedContext);
-        assertTrue(dpm.isActivePasswordSufficient());
+        assertThat(dpm.isActivePasswordSufficient()).isTrue();
 
         // This call simulates the user entering the password for the first time after a reboot.
         // This causes password metrics to be reloaded into memory.  Until this happens,
@@ -4854,23 +5024,24 @@
         // requirements.  This is a known limitation of the current implementation of
         // isActivePasswordSufficient() - see b/34218769.
         setActivePasswordState(passwordMetricsNoSymbols);
-        assertTrue(dpm.isActivePasswordSufficient());
+        assertThat(dpm.isActivePasswordSufficient()).isTrue();
 
         dpm.setPasswordMinimumSymbols(admin1, 1);
         // This assertion would fail if we had not called setActivePasswordState() again after
         // initializeDpms() - see previous comment.
-        assertFalse(dpm.isActivePasswordSufficient());
+        assertThat(dpm.isActivePasswordSufficient()).isFalse();
 
         initializeDpms();
         reset(mContext.spiedContext);
-        assertFalse(dpm.isActivePasswordSufficient());
+        assertThat(dpm.isActivePasswordSufficient()).isFalse();
 
         PasswordMetrics passwordMetricsWithSymbols = computeForPassword("abcd.XY5".getBytes());
 
         setActivePasswordState(passwordMetricsWithSymbols);
-        assertTrue(dpm.isActivePasswordSufficient());
+        assertThat(dpm.isActivePasswordSufficient()).isTrue();
     }
 
+    @Test
     public void testIsActivePasswordSufficient_noLockScreen() throws Exception {
         // If there is no lock screen, the password is considered empty no matter what, because
         // it provides no security.
@@ -4885,7 +5056,7 @@
                 .thenReturn(new PasswordMetrics(CREDENTIAL_TYPE_NONE));
 
         // If no password requirements are set, isActivePasswordSufficient should succeed.
-        assertTrue(dpm.isActivePasswordSufficient());
+        assertThat(dpm.isActivePasswordSufficient()).isTrue();
 
         // Now set some password quality requirements.
         dpm.setPasswordQuality(admin1, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
@@ -4900,9 +5071,10 @@
                 MockUtils.checkUserHandle(userHandle));
 
         // The active (nonexistent) password doesn't comply with the requirements.
-        assertFalse(dpm.isActivePasswordSufficient());
+        assertThat(dpm.isActivePasswordSufficient()).isFalse();
     }
 
+    @Test
     public void testIsPasswordSufficientAfterProfileUnification() throws Exception {
         final int managedProfileUserId = CALLER_USER_HANDLE;
         final int managedProfileAdminUid =
@@ -4921,13 +5093,13 @@
 
         // Numeric password is compliant with current requirement (QUALITY_NUMERIC set explicitly
         // on the parent admin)
-        assertTrue(dpm.isPasswordSufficientAfterProfileUnification(UserHandle.USER_SYSTEM,
-                UserHandle.USER_NULL));
+        assertThat(dpm.isPasswordSufficientAfterProfileUnification(UserHandle.USER_SYSTEM,
+        UserHandle.USER_NULL)).isTrue();
         // Numeric password is not compliant if profile is to be unified: the profile has a
         // QUALITY_ALPHABETIC policy on itself which will be enforced on the password after
         // unification.
-        assertFalse(dpm.isPasswordSufficientAfterProfileUnification(UserHandle.USER_SYSTEM,
-                managedProfileUserId));
+        assertThat(dpm.isPasswordSufficientAfterProfileUnification(UserHandle.USER_SYSTEM,
+        managedProfileUserId)).isFalse();
     }
 
     private void setActivePasswordState(PasswordMetrics passwordMetrics)
@@ -4961,6 +5133,7 @@
         mContext.binder.restoreCallingIdentity(ident);
     }
 
+    @Test
     public void testIsCurrentInputMethodSetByOwnerForDeviceOwner() throws Exception {
         final String currentIme = Settings.Secure.DEFAULT_INPUT_METHOD;
         final Uri currentImeUri = Settings.Secure.getUriFor(currentIme);
@@ -4976,70 +5149,71 @@
 
         // First and second user set IMEs manually.
         mContext.binder.callingUid = firstUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
 
         // Device owner changes IME for first user.
         mContext.binder.callingUid = deviceOwnerUid;
-        when(getServices().settings.settingsSecureGetStringForUser(currentIme, UserHandle.USER_SYSTEM))
-                .thenReturn("ime1");
+        when(getServices().settings.settingsSecureGetStringForUser(currentIme,
+                UserHandle.USER_SYSTEM)).thenReturn("ime1");
         dpm.setSecureSetting(admin1, currentIme, "ime2");
         verify(getServices().settings).settingsSecurePutStringForUser(currentIme, "ime2",
                 UserHandle.USER_SYSTEM);
         reset(getServices().settings);
         dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
         mContext.binder.callingUid = firstUserSystemUid;
-        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
 
         // Second user changes IME manually.
         dpms.notifyChangeToContentObserver(currentImeUri, CALLER_USER_HANDLE);
         mContext.binder.callingUid = firstUserSystemUid;
-        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
 
         // First user changes IME manually.
         dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
         mContext.binder.callingUid = firstUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
 
         // Device owner changes IME for first user again.
         mContext.binder.callingUid = deviceOwnerUid;
-        when(getServices().settings.settingsSecureGetStringForUser(currentIme, UserHandle.USER_SYSTEM))
-                .thenReturn("ime2");
+        when(getServices().settings.settingsSecureGetStringForUser(currentIme,
+                UserHandle.USER_SYSTEM)).thenReturn("ime2");
         dpm.setSecureSetting(admin1, currentIme, "ime3");
         verify(getServices().settings).settingsSecurePutStringForUser(currentIme, "ime3",
                 UserHandle.USER_SYSTEM);
         dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
         mContext.binder.callingUid = firstUserSystemUid;
-        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
 
         // Restarting the DPMS should not lose information.
         initializeDpms();
         mContext.binder.callingUid = firstUserSystemUid;
-        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
 
         // Device owner can find out whether it set the current IME itself.
         mContext.binder.callingUid = deviceOwnerUid;
-        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
 
         // Removing the device owner should clear the information that it set the current IME.
         clearDeviceOwner();
         mContext.binder.callingUid = firstUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
     }
 
+    @Test
     public void testIsCurrentInputMethodSetByOwnerForProfileOwner() throws Exception {
         final String currentIme = Settings.Secure.DEFAULT_INPUT_METHOD;
         final Uri currentImeUri = Settings.Secure.getUriFor(currentIme);
@@ -5055,9 +5229,9 @@
 
         // First and second user set IMEs manually.
         mContext.binder.callingUid = firstUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
 
         // Profile owner changes IME for second user.
         mContext.binder.callingUid = profileOwnerUid;
@@ -5069,23 +5243,23 @@
         reset(getServices().settings);
         dpms.notifyChangeToContentObserver(currentImeUri, CALLER_USER_HANDLE);
         mContext.binder.callingUid = firstUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
 
         // First user changes IME manually.
         dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
         mContext.binder.callingUid = firstUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
 
         // Second user changes IME manually.
         dpms.notifyChangeToContentObserver(currentImeUri, CALLER_USER_HANDLE);
         mContext.binder.callingUid = firstUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
 
         // Profile owner changes IME for second user again.
         mContext.binder.callingUid = profileOwnerUid;
@@ -5096,29 +5270,30 @@
                 CALLER_USER_HANDLE);
         dpms.notifyChangeToContentObserver(currentImeUri, CALLER_USER_HANDLE);
         mContext.binder.callingUid = firstUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
 
         // Restarting the DPMS should not lose information.
         initializeDpms();
         mContext.binder.callingUid = firstUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
 
         // Profile owner can find out whether it set the current IME itself.
         mContext.binder.callingUid = profileOwnerUid;
-        assertTrue(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
 
         // Removing the profile owner should clear the information that it set the current IME.
         dpm.clearProfileOwner(admin1);
         mContext.binder.callingUid = firstUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
         mContext.binder.callingUid = secondUserSystemUid;
-        assertFalse(dpm.isCurrentInputMethodSetByOwner());
+        assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
     }
 
+    @Test
     public void testSetPermittedCrossProfileNotificationListeners_unavailableForDo()
             throws Exception {
         // Set up a device owner.
@@ -5127,6 +5302,7 @@
         assertSetPermittedCrossProfileNotificationListenersUnavailable(mContext.binder.callingUid);
     }
 
+    @Test
     public void testSetPermittedCrossProfileNotificationListeners_unavailableForPoOnUser()
             throws Exception {
         // Set up a profile owner.
@@ -5141,23 +5317,24 @@
         final int userId = UserHandle.getUserId(adminUid);
 
         final String packageName = "some.package";
-        assertFalse(dpms.setPermittedCrossProfileNotificationListeners(
-                admin1, Collections.singletonList(packageName)));
-        assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1));
+        assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+        admin1, Collections.singletonList(packageName))).isFalse();
+        assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1)).isNull();
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertTrue(dpms.isNotificationListenerServicePermitted(packageName, userId));
+        assertThat(dpms.isNotificationListenerServicePermitted(packageName, userId)).isTrue();
 
         // Attempt to set to empty list (which means no listener is allowlisted)
         mContext.binder.callingUid = adminUid;
-        assertFalse(dpms.setPermittedCrossProfileNotificationListeners(
-                admin1, Collections.emptyList()));
-        assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1));
+        assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+                admin1, Collections.emptyList())).isFalse();
+        assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1)).isNull();
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertTrue(dpms.isNotificationListenerServicePermitted(packageName, userId));
+        assertThat(dpms.isNotificationListenerServicePermitted(packageName, userId)).isTrue();
     }
 
+    @Test
     public void testIsNotificationListenerServicePermitted_onlySystemCanCall() throws Exception {
         // Set up a managed profile
         final int MANAGED_PROFILE_USER_ID = 15;
@@ -5171,8 +5348,8 @@
                 UserHandle.USER_SYSTEM, // We check the packageInfo from the primary user.
                 /*appId=*/ 12345, /*flags=*/ 0);
 
-        assertTrue(dpms.setPermittedCrossProfileNotificationListeners(
-                admin1, Collections.singletonList(permittedListener)));
+        assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+        admin1, Collections.singletonList(permittedListener))).isTrue();
 
         // isNotificationListenerServicePermitted should throw if not called from System.
         assertExpectException(SecurityException.class, /* messageRegex= */ null,
@@ -5180,10 +5357,11 @@
                         permittedListener, MANAGED_PROFILE_USER_ID));
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                permittedListener, MANAGED_PROFILE_USER_ID));
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        permittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
     }
 
+    @Test
     public void testSetPermittedCrossProfileNotificationListeners_managedProfile()
             throws Exception {
         // Set up a managed profile
@@ -5212,63 +5390,64 @@
                 ++appId, ApplicationInfo.FLAG_SYSTEM);
 
         // By default all packages are allowed
-        assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1));
+        assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1)).isNull();
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                permittedListener, MANAGED_PROFILE_USER_ID));
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                notPermittedListener, MANAGED_PROFILE_USER_ID));
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                systemListener, MANAGED_PROFILE_USER_ID));
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        permittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        notPermittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
 
         // Setting only one package in the allowlist
         mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
-        assertTrue(dpms.setPermittedCrossProfileNotificationListeners(
-                admin1, Collections.singletonList(permittedListener)));
+        assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+        admin1, Collections.singletonList(permittedListener))).isTrue();
         final List<String> permittedListeners =
                 dpms.getPermittedCrossProfileNotificationListeners(admin1);
-        assertEquals(1, permittedListeners.size());
-        assertEquals(permittedListener, permittedListeners.get(0));
+        assertThat(permittedListeners.size()).isEqualTo(1);
+        assertThat(permittedListeners.get(0)).isEqualTo(permittedListener);
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                permittedListener, MANAGED_PROFILE_USER_ID));
-        assertFalse(dpms.isNotificationListenerServicePermitted(
-                notPermittedListener, MANAGED_PROFILE_USER_ID));
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        permittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        notPermittedListener, MANAGED_PROFILE_USER_ID)).isFalse();
         // System packages are always allowed (even if not in the allowlist)
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                systemListener, MANAGED_PROFILE_USER_ID));
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
 
         // Setting an empty allowlist - only system listeners allowed
         mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
-        assertTrue(dpms.setPermittedCrossProfileNotificationListeners(
-                admin1, Collections.emptyList()));
-        assertEquals(0, dpms.getPermittedCrossProfileNotificationListeners(admin1).size());
+        assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+                admin1, Collections.emptyList())).isTrue();
+        assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1).size()).isEqualTo(0);
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertFalse(dpms.isNotificationListenerServicePermitted(
-                permittedListener, MANAGED_PROFILE_USER_ID));
-        assertFalse(dpms.isNotificationListenerServicePermitted(
-                notPermittedListener, MANAGED_PROFILE_USER_ID));
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        permittedListener, MANAGED_PROFILE_USER_ID)).isFalse();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        notPermittedListener, MANAGED_PROFILE_USER_ID)).isFalse();
         // System packages are always allowed (even if not in the allowlist)
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                systemListener, MANAGED_PROFILE_USER_ID));
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
 
         // Setting a null allowlist - all listeners allowed
         mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
-        assertTrue(dpms.setPermittedCrossProfileNotificationListeners(admin1, null));
-        assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1));
+        assertThat(dpms.setPermittedCrossProfileNotificationListeners(admin1, null)).isTrue();
+        assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1)).isNull();
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                permittedListener, MANAGED_PROFILE_USER_ID));
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                notPermittedListener, MANAGED_PROFILE_USER_ID));
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                systemListener, MANAGED_PROFILE_USER_ID));
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        permittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        notPermittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
     }
 
+    @Test
     public void testSetPermittedCrossProfileNotificationListeners_doesNotAffectPrimaryProfile()
             throws Exception {
         // Set up a managed profile
@@ -5291,36 +5470,37 @@
                 ++appId, ApplicationInfo.FLAG_SYSTEM);
 
         // By default all packages are allowed (for all profiles)
-        assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1));
+        assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1)).isNull();
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                nonSystemPackage, MANAGED_PROFILE_USER_ID));
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                systemListener, MANAGED_PROFILE_USER_ID));
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                nonSystemPackage, UserHandle.USER_SYSTEM));
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                systemListener, UserHandle.USER_SYSTEM));
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        nonSystemPackage, MANAGED_PROFILE_USER_ID)).isTrue();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        systemListener, UserHandle.USER_SYSTEM)).isTrue();
 
         // Setting an empty allowlist - only system listeners allowed in managed profile, but
         // all allowed in primary profile
         mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
-        assertTrue(dpms.setPermittedCrossProfileNotificationListeners(
-                admin1, Collections.emptyList()));
-        assertEquals(0, dpms.getPermittedCrossProfileNotificationListeners(admin1).size());
+        assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+                admin1, Collections.emptyList())).isTrue();
+        assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1).size()).isEqualTo(0);
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertFalse(dpms.isNotificationListenerServicePermitted(
-                nonSystemPackage, MANAGED_PROFILE_USER_ID));
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                systemListener, MANAGED_PROFILE_USER_ID));
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                nonSystemPackage, UserHandle.USER_SYSTEM));
-        assertTrue(dpms.isNotificationListenerServicePermitted(
-                systemListener, UserHandle.USER_SYSTEM));
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        nonSystemPackage, MANAGED_PROFILE_USER_ID)).isFalse();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue();
+        assertThat(dpms.isNotificationListenerServicePermitted(
+        systemListener, UserHandle.USER_SYSTEM)).isTrue();
     }
 
+    @Test
     public void testGetOwnerInstalledCaCertsForDeviceOwner() throws Exception {
         mServiceContext.packageName = mRealTestContext.getPackageName();
         mServiceContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
@@ -5330,6 +5510,7 @@
         verifyCanGetOwnerInstalledCaCerts(admin1, mAdmin1Context);
     }
 
+    @Test
     public void testGetOwnerInstalledCaCertsForProfileOwner() throws Exception {
         mServiceContext.packageName = mRealTestContext.getPackageName();
         mServiceContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
@@ -5340,6 +5521,7 @@
         verifyCantGetOwnerInstalledCaCertsProfileOwnerRemoval(admin1, mAdmin1Context);
     }
 
+    @Test
     public void testGetOwnerInstalledCaCertsForDelegate() throws Exception {
         mServiceContext.packageName = mRealTestContext.getPackageName();
         mServiceContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
@@ -5359,6 +5541,7 @@
         verifyCantGetOwnerInstalledCaCertsProfileOwnerRemoval(null, caller);
     }
 
+    @Test
     public void testDisallowSharingIntoProfileSetRestriction() {
         when(mServiceContext.resources.getString(R.string.config_managed_provisioning_package))
                 .thenReturn("com.android.managedprovisioning");
@@ -5371,6 +5554,7 @@
         verifyDataSharingChangedBroadcast();
     }
 
+    @Test
     public void testDisallowSharingIntoProfileClearRestriction() {
         when(mServiceContext.resources.getString(R.string.config_managed_provisioning_package))
                 .thenReturn("com.android.managedprovisioning");
@@ -5383,6 +5567,7 @@
         verifyDataSharingChangedBroadcast();
     }
 
+    @Test
     public void testDisallowSharingIntoProfileUnchanged() {
         RestrictionsListener listener = new RestrictionsListener(mContext);
         listener.onUserRestrictionsChanged(CALLER_USER_HANDLE, new Bundle(), new Bundle());
@@ -5399,6 +5584,7 @@
                 MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
     }
 
+    @Test
     public void testOverrideApnAPIsFailWithPO() throws Exception {
         setupProfileOwner();
         ApnSetting apn = (new ApnSetting.Builder())
@@ -5446,13 +5632,14 @@
         runAsCaller(callerContext, dpms, (dpm) -> {
             when(getServices().keyChainConnection.getService().installCaCertificate(caCert))
                         .thenReturn(alias);
-            assertTrue(dpm.installCaCert(caller, caCert));
+            assertThat(dpm.installCaCert(caller, caCert)).isTrue();
             when(getServices().keyChainConnection.getService().getUserCaAliases())
                     .thenReturn(asSlice(new String[] {alias}));
         });
 
-        getServices().injectBroadcast(mServiceContext, new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
-                .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
+        getServices().injectBroadcast(mServiceContext,
+                new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
+                        .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
                 callerUser.getIdentifier());
         flushTasks(dpms);
 
@@ -5461,25 +5648,27 @@
         // Device Owner / Profile Owner can find out which CA certs were installed by itself.
         runAsCaller(admin1Context, dpms, (dpm) -> {
             final List<String> installedCaCerts = dpm.getOwnerInstalledCaCerts(callerUser);
-            assertEquals(Collections.singletonList(alias), installedCaCerts);
+            assertThat(installedCaCerts).isEqualTo(Collections.singletonList(alias));
             ownerInstalledCaCerts.addAll(installedCaCerts);
         });
 
         // Restarting the DPMS should not lose information.
         initializeDpms();
-        runAsCaller(admin1Context, dpms, (dpm) ->
-                assertEquals(ownerInstalledCaCerts, dpm.getOwnerInstalledCaCerts(callerUser)));
+        runAsCaller(admin1Context, dpms,
+                (dpm) -> assertThat(dpm.getOwnerInstalledCaCerts(callerUser))
+                        .isEqualTo(ownerInstalledCaCerts));
 
         // System can find out which CA certs were installed by the Device Owner / Profile Owner.
         runAsCaller(serviceContext, dpms, (dpm) -> {
-            assertEquals(ownerInstalledCaCerts, dpm.getOwnerInstalledCaCerts(callerUser));
+            assertThat(dpm.getOwnerInstalledCaCerts(callerUser)).isEqualTo(ownerInstalledCaCerts);
 
             // Remove the CA cert.
             reset(getServices().keyChainConnection.getService());
         });
 
-        getServices().injectBroadcast(mServiceContext, new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
-                .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
+        getServices().injectBroadcast(mServiceContext,
+                new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
+                        .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
                 callerUser.getIdentifier());
         flushTasks(dpms);
 
@@ -5516,14 +5705,15 @@
         runAsCaller(callerContext, dpms, (dpm) -> {
             when(getServices().keyChainConnection.getService().installCaCertificate(caCert))
                     .thenReturn(alias);
-            assertTrue(dpm.installCaCert(callerName, caCert));
+            assertThat(dpm.installCaCert(callerName, caCert)).isTrue();
         });
 
         // Fake the CA cert as having been installed
         when(getServices().keyChainConnection.getService().getUserCaAliases())
                 .thenReturn(asSlice(new String[] {alias}));
-        getServices().injectBroadcast(mServiceContext, new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
-                .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
+        getServices().injectBroadcast(mServiceContext,
+                new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
+                        .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
                 callerUser.getIdentifier());
         flushTasks(dpms);
 
@@ -5532,8 +5722,8 @@
 
         runAsCaller(serviceContext, dpms, (dpm) -> {
             final List<String> ownerInstalledCaCerts = dpm.getOwnerInstalledCaCerts(callerUser);
-            assertNotNull(ownerInstalledCaCerts);
-            assertTrue(ownerInstalledCaCerts.isEmpty());
+            assertThat(ownerInstalledCaCerts).isNotNull();
+            assertThat(ownerInstalledCaCerts.isEmpty()).isTrue();
         });
     }
 
@@ -5541,9 +5731,10 @@
         int[] gotFlags = DevicePolicyManagerService.translateIdAttestationFlags(attestationFlags);
         Arrays.sort(gotFlags);
         Arrays.sort(expectedFlags);
-        assertTrue(Arrays.equals(expectedFlags, gotFlags));
+        assertThat(Arrays.equals(expectedFlags, gotFlags)).isTrue();
     }
 
+    @Test
     public void testTranslationOfIdAttestationFlag() {
         int[] allIdTypes = new int[]{ID_TYPE_SERIAL, ID_TYPE_IMEI, ID_TYPE_MEID};
         int[] correspondingAttUtilsTypes = new int[]{
@@ -5551,7 +5742,7 @@
             AttestationUtils.ID_TYPE_MEID};
 
         // Test translation of zero flags
-        assertNull(DevicePolicyManagerService.translateIdAttestationFlags(0));
+        assertThat(DevicePolicyManagerService.translateIdAttestationFlags(0)).isNull();
 
         // Test translation of the ID_TYPE_BASE_INFO flag, which should yield an empty, but
         // non-null array
@@ -5578,39 +5769,41 @@
                     AttestationUtils.ID_TYPE_MEID});
     }
 
+    @Test
     public void testRevertDeviceOwnership_noMetadataFile() throws Exception {
         setDeviceOwner();
         initializeDpms();
-        assertFalse(getMockTransferMetadataManager().metadataFileExists());
-        assertTrue(dpms.isDeviceOwner(admin1, UserHandle.USER_SYSTEM));
-        assertTrue(dpms.isAdminActive(admin1, UserHandle.USER_SYSTEM));
+        assertThat(getMockTransferMetadataManager().metadataFileExists()).isFalse();
+        assertThat(dpms.isDeviceOwner(admin1, UserHandle.USER_SYSTEM)).isTrue();
+        assertThat(dpms.isAdminActive(admin1, UserHandle.USER_SYSTEM)).isTrue();
     }
 
-    // @FlakyTest(bugId = 148934649)
-    // public void testRevertDeviceOwnership_adminAndDeviceMigrated() throws Exception {
-    //     DpmTestUtils.writeInputStreamToFile(
-    //             getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
-    //             getDeviceOwnerPoliciesFile());
-    //     DpmTestUtils.writeInputStreamToFile(
-    //             getRawStream(com.android.frameworks.servicestests.R.raw.device_owner_migrated),
-    //             getDeviceOwnerFile());
-    //     assertDeviceOwnershipRevertedWithFakeTransferMetadata();
-    // }
+    @FlakyTest(bugId = 148934649)
+    @Test
+    public void testRevertDeviceOwnership_adminAndDeviceMigrated() throws Exception {
+        DpmTestUtils.writeInputStreamToFile(
+                getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+                getDeviceOwnerPoliciesFile());
+        DpmTestUtils.writeInputStreamToFile(
+                getRawStream(com.android.frameworks.servicestests.R.raw.device_owner_migrated),
+                getDeviceOwnerFile());
+        assertDeviceOwnershipRevertedWithFakeTransferMetadata();
+    }
 
-    // @FlakyTest(bugId = 148934649)
-    // public void testRevertDeviceOwnership_deviceNotMigrated()
-    //         throws Exception {
-    //     DpmTestUtils.writeInputStreamToFile(
-    //             getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
-    //             getDeviceOwnerPoliciesFile());
-    //     DpmTestUtils.writeInputStreamToFile(
-    //             getRawStream(com.android.frameworks.servicestests.R.raw.device_owner_not_migrated),
-    //             getDeviceOwnerFile());
-    //     assertDeviceOwnershipRevertedWithFakeTransferMetadata();
-    // }
+    @FlakyTest(bugId = 148934649)
+    @Test
+    public void testRevertDeviceOwnership_deviceNotMigrated() throws Exception {
+        DpmTestUtils.writeInputStreamToFile(
+                getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+                getDeviceOwnerPoliciesFile());
+        DpmTestUtils.writeInputStreamToFile(
+                getRawStream(com.android.frameworks.servicestests.R.raw.device_owner_not_migrated),
+                getDeviceOwnerFile());
+        assertDeviceOwnershipRevertedWithFakeTransferMetadata();
+    }
 
-    public void testRevertDeviceOwnership_adminAndDeviceNotMigrated()
-            throws Exception {
+    @Test
+    public void testRevertDeviceOwnership_adminAndDeviceNotMigrated() throws Exception {
         DpmTestUtils.writeInputStreamToFile(
                 getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_not_migrated),
                 getDeviceOwnerPoliciesFile());
@@ -5620,40 +5813,44 @@
         assertDeviceOwnershipRevertedWithFakeTransferMetadata();
     }
 
+    @Test
     public void testRevertProfileOwnership_noMetadataFile() throws Exception {
         setupProfileOwner();
         initializeDpms();
-        assertFalse(getMockTransferMetadataManager().metadataFileExists());
-        assertTrue(dpms.isProfileOwner(admin1, CALLER_USER_HANDLE));
-        assertTrue(dpms.isAdminActive(admin1, CALLER_USER_HANDLE));
+        assertThat(getMockTransferMetadataManager().metadataFileExists()).isFalse();
+        assertThat(dpms.isProfileOwner(admin1, CALLER_USER_HANDLE)).isTrue();
+        assertThat(dpms.isAdminActive(admin1, CALLER_USER_HANDLE)).isTrue();
     }
 
-    // @FlakyTest(bugId = 148934649)
-    // public void testRevertProfileOwnership_adminAndProfileMigrated() throws Exception {
-    //     getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
-    //             UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
-    //     DpmTestUtils.writeInputStreamToFile(
-    //             getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
-    //             getProfileOwnerPoliciesFile());
-    //     DpmTestUtils.writeInputStreamToFile(
-    //             getRawStream(com.android.frameworks.servicestests.R.raw.profile_owner_migrated),
-    //             getProfileOwnerFile());
-    //     assertProfileOwnershipRevertedWithFakeTransferMetadata();
-    // }
+    @FlakyTest(bugId = 148934649)
+    @Test
+    public void testRevertProfileOwnership_adminAndProfileMigrated() throws Exception {
+        getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+                UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
+        DpmTestUtils.writeInputStreamToFile(
+                getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+                getProfileOwnerPoliciesFile());
+        DpmTestUtils.writeInputStreamToFile(
+                getRawStream(com.android.frameworks.servicestests.R.raw.profile_owner_migrated),
+                getProfileOwnerFile());
+        assertProfileOwnershipRevertedWithFakeTransferMetadata();
+    }
 
-    // @FlakyTest(bugId = 148934649)
-    // public void testRevertProfileOwnership_profileNotMigrated() throws Exception {
-    //     getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
-    //             UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
-    //     DpmTestUtils.writeInputStreamToFile(
-    //             getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
-    //             getProfileOwnerPoliciesFile());
-    //     DpmTestUtils.writeInputStreamToFile(
-    //             getRawStream(com.android.frameworks.servicestests.R.raw.profile_owner_not_migrated),
-    //             getProfileOwnerFile());
-    //     assertProfileOwnershipRevertedWithFakeTransferMetadata();
-    // }
+    @FlakyTest(bugId = 148934649)
+    @Test
+    public void testRevertProfileOwnership_profileNotMigrated() throws Exception {
+        getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+                UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
+        DpmTestUtils.writeInputStreamToFile(
+                getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+                getProfileOwnerPoliciesFile());
+        DpmTestUtils.writeInputStreamToFile(
+                getRawStream(com.android.frameworks.servicestests.R.raw.profile_owner_not_migrated),
+                getProfileOwnerFile());
+        assertProfileOwnershipRevertedWithFakeTransferMetadata();
+    }
 
+    @Test
     public void testRevertProfileOwnership_adminAndProfileNotMigrated() throws Exception {
         getServices().addUser(CALLER_USER_HANDLE, 0,
                 UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
@@ -5666,6 +5863,7 @@
         assertProfileOwnershipRevertedWithFakeTransferMetadata();
     }
 
+    @Test
     public void testGrantDeviceIdsAccess_notToProfileOwner() throws Exception {
         setupProfileOwner();
         configureContextForAccess(mContext, false);
@@ -5674,6 +5872,7 @@
                 () -> dpm.markProfileOwnerOnOrganizationOwnedDevice(admin2));
     }
 
+    @Test
     public void testGrantDeviceIdsAccess_notByAuthorizedCaller() throws Exception {
         setupProfileOwner();
         configureContextForAccess(mContext, false);
@@ -5682,6 +5881,7 @@
                 () -> dpm.markProfileOwnerOnOrganizationOwnedDevice(admin1));
     }
 
+    @Test
     public void testGrantDeviceIdsAccess_byAuthorizedSystemCaller() throws Exception {
         setupProfileOwner();
 
@@ -5700,6 +5900,7 @@
                 .thenReturn(UserHandle.SYSTEM);
     }
 
+    @Test
     public void testGrantDeviceIdsAccess_byAuthorizedManagedProvisioning() throws Exception {
         setupProfileOwner();
 
@@ -5719,6 +5920,7 @@
         }
     }
 
+    @Test
     public void testEnforceCallerCanRequestDeviceIdAttestation_deviceOwnerCaller()
             throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -5741,6 +5943,7 @@
                         dpms.getCallerIdentity(admin2)));
     }
 
+    @Test
     public void testEnforceCallerCanRequestDeviceIdAttestation_profileOwnerCaller()
             throws Exception {
         configureContextForAccess(mContext, false);
@@ -5781,6 +5984,7 @@
         }
     }
 
+    @Test
     public void testEnforceCallerCanRequestDeviceIdAttestation_delegateCaller() throws Exception {
         setupProfileOwner();
         markDelegatedCertInstallerAsInstalled();
@@ -5800,6 +6004,7 @@
                 dpms.getCallerIdentity(null, DpmMockContext.DELEGATE_PACKAGE_NAME)));
     }
 
+    @Test
     public void testEnforceCallerCanRequestDeviceIdAttestation_delegateCallerWithoutPermissions()
             throws Exception {
         setupProfileOwner();
@@ -5821,6 +6026,7 @@
         });
     }
 
+    @Test
     public void testGetPasswordComplexity_securityExceptionNotThrownForParentInstance() {
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5830,9 +6036,10 @@
 
         parentDpm.getPasswordComplexity();
 
-        assertEquals(PASSWORD_COMPLEXITY_NONE, dpm.getPasswordComplexity());
+        assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_NONE);
     }
 
+    @Test
     public void testGetPasswordComplexity_illegalStateExceptionIfLocked() {
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5841,6 +6048,7 @@
         assertThrows(IllegalStateException.class, () -> dpm.getPasswordComplexity());
     }
 
+    @Test
     public void testGetPasswordComplexity_securityExceptionWithoutPermissions() {
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5850,6 +6058,7 @@
     }
 
 
+    @Test
     public void testGetPasswordComplexity_currentUserNoPassword() {
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5859,9 +6068,10 @@
         when(getServices().userManager.getCredentialOwnerProfile(CALLER_USER_HANDLE))
                 .thenReturn(CALLER_USER_HANDLE);
 
-        assertEquals(PASSWORD_COMPLEXITY_NONE, dpm.getPasswordComplexity());
+        assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_NONE);
     }
 
+    @Test
     public void testGetPasswordComplexity_currentUserHasPassword() {
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5874,9 +6084,10 @@
                 .getUserPasswordMetrics(CALLER_USER_HANDLE))
                 .thenReturn(computeForPassword("asdf".getBytes()));
 
-        assertEquals(PASSWORD_COMPLEXITY_MEDIUM, dpm.getPasswordComplexity());
+        assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_MEDIUM);
     }
 
+    @Test
     public void testGetPasswordComplexity_unifiedChallengeReturnsParentUserPassword() {
         mContext.binder.callingUid = DpmMockContext.CALLER_UID;
         when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5896,23 +6107,25 @@
                 .getUserPasswordMetrics(parentUser.id))
                 .thenReturn(computeForPassword("parentUser".getBytes()));
 
-        assertEquals(PASSWORD_COMPLEXITY_HIGH, dpm.getPasswordComplexity());
+        assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_HIGH);
     }
 
+    @Test
     public void testCrossProfileCalendarPackages_initiallyEmpty() {
         setAsProfileOwner(admin1);
         final Set<String> packages = dpm.getCrossProfileCalendarPackages(admin1);
         assertCrossProfileCalendarPackagesEqual(packages, Collections.emptySet());
     }
 
+    @Test
     public void testCrossProfileCalendarPackages_reopenDpms() {
         setAsProfileOwner(admin1);
         dpm.setCrossProfileCalendarPackages(admin1, null);
         Set<String> packages = dpm.getCrossProfileCalendarPackages(admin1);
-        assertTrue(packages == null);
+        assertThat(packages == null).isTrue();
         initializeDpms();
         packages = dpm.getCrossProfileCalendarPackages(admin1);
-        assertTrue(packages == null);
+        assertThat(packages == null).isTrue();
 
         dpm.setCrossProfileCalendarPackages(admin1, Collections.emptySet());
         packages = dpm.getCrossProfileCalendarPackages(admin1);
@@ -5932,21 +6145,22 @@
     }
 
     private void assertCrossProfileCalendarPackagesEqual(Set<String> expected, Set<String> actual) {
-        assertTrue(expected != null);
-        assertTrue(actual != null);
-        assertTrue(expected.containsAll(actual));
-        assertTrue(actual.containsAll(expected));
+        assertThat(expected).isNotNull();
+        assertThat(actual).isNotNull();
+        assertThat(actual).containsExactlyElementsIn(expected);
     }
 
+    @Test
     public void testIsPackageAllowedToAccessCalendar_adminNotAllowed() {
         setAsProfileOwner(admin1);
         dpm.setCrossProfileCalendarPackages(admin1, Collections.emptySet());
         when(getServices().settings.settingsSecureGetIntForUser(
                 Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
                 0, CALLER_USER_HANDLE)).thenReturn(1);
-        assertFalse(dpm.isPackageAllowedToAccessCalendar("TEST_PACKAGE"));
+        assertThat(dpm.isPackageAllowedToAccessCalendar("TEST_PACKAGE")).isFalse();
     }
 
+    @Test
     public void testIsPackageAllowedToAccessCalendar_settingOff() {
         final String testPackage = "TEST_PACKAGE";
         setAsProfileOwner(admin1);
@@ -5954,9 +6168,10 @@
         when(getServices().settings.settingsSecureGetIntForUser(
                 Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
                 0, CALLER_USER_HANDLE)).thenReturn(0);
-        assertFalse(dpm.isPackageAllowedToAccessCalendar(testPackage));
+        assertThat(dpm.isPackageAllowedToAccessCalendar(testPackage)).isFalse();
     }
 
+    @Test
     public void testIsPackageAllowedToAccessCalendar_bothAllowed() {
         final String testPackage = "TEST_PACKAGE";
         setAsProfileOwner(admin1);
@@ -5964,9 +6179,10 @@
         when(getServices().settings.settingsSecureGetIntForUser(
                 Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
                 0, CALLER_USER_HANDLE)).thenReturn(1);
-        assertTrue(dpm.isPackageAllowedToAccessCalendar(testPackage));
+        assertThat(dpm.isPackageAllowedToAccessCalendar(testPackage)).isTrue();
     }
 
+    @Test
     public void testSetUserControlDisabledPackages_asDO() throws Exception {
         final List<String> testPackages = new ArrayList<>();
         testPackages.add("package_1");
@@ -5979,9 +6195,10 @@
 
         verify(getServices().packageManagerInternal).setDeviceOwnerProtectedPackages(testPackages);
 
-        assertEquals(testPackages, dpm.getUserControlDisabledPackages(admin1));
+        assertThat(dpm.getUserControlDisabledPackages(admin1)).isEqualTo(testPackages);
     }
 
+    @Test
     public void testSetUserControlDisabledPackages_failingAsPO() throws Exception {
         final List<String> testPackages = new ArrayList<>();
         testPackages.add("package_1");
@@ -6008,28 +6225,32 @@
         mServiceContext.binder.restoreCallingIdentity(ident);
     }
 
+    @Test
     public void testGetCrossProfilePackages_notSet_returnsEmpty() {
         setAsProfileOwner(admin1);
-        assertTrue(dpm.getCrossProfilePackages(admin1).isEmpty());
+        assertThat(dpm.getCrossProfilePackages(admin1).isEmpty()).isTrue();
     }
 
+    @Test
     public void testGetCrossProfilePackages_notSet_dpmsReinitialized_returnsEmpty() {
         setAsProfileOwner(admin1);
 
         initializeDpms();
 
-        assertTrue(dpm.getCrossProfilePackages(admin1).isEmpty());
+        assertThat(dpm.getCrossProfilePackages(admin1).isEmpty()).isTrue();
     }
 
+    @Test
     public void testGetCrossProfilePackages_whenSet_returnsEqual() {
         setAsProfileOwner(admin1);
         Set<String> packages = Collections.singleton("TEST_PACKAGE");
 
         dpm.setCrossProfilePackages(admin1, packages);
 
-        assertEquals(packages, dpm.getCrossProfilePackages(admin1));
+        assertThat(dpm.getCrossProfilePackages(admin1)).isEqualTo(packages);
     }
 
+    @Test
     public void testGetCrossProfilePackages_whenSet_dpmsReinitialized_returnsEqual() {
         setAsProfileOwner(admin1);
         Set<String> packages = Collections.singleton("TEST_PACKAGE");
@@ -6037,9 +6258,10 @@
         dpm.setCrossProfilePackages(admin1, packages);
         initializeDpms();
 
-        assertEquals(packages, dpm.getCrossProfilePackages(admin1));
+        assertThat(dpm.getCrossProfilePackages(admin1)).isEqualTo(packages);
     }
 
+    @Test
     public void testGetAllCrossProfilePackages_notSet_returnsEmpty() throws Exception {
         addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
         mContext.packageName = admin1.getPackageName();
@@ -6047,9 +6269,10 @@
         setCrossProfileAppsList();
         setVendorCrossProfileAppsList();
 
-        assertTrue(dpm.getAllCrossProfilePackages().isEmpty());
+        assertThat(dpm.getAllCrossProfilePackages().isEmpty()).isTrue();
     }
 
+    @Test
     public void testGetAllCrossProfilePackages_notSet_dpmsReinitialized_returnsEmpty()
             throws Exception {
         addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
@@ -6059,9 +6282,10 @@
         setVendorCrossProfileAppsList();
         initializeDpms();
 
-        assertTrue(dpm.getAllCrossProfilePackages().isEmpty());
+        assertThat(dpm.getAllCrossProfilePackages().isEmpty()).isTrue();
     }
 
+    @Test
     public void testGetAllCrossProfilePackages_whenSet_returnsCombinedSet() throws Exception {
         addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
         final Set<String> packages = Sets.newSet("TEST_PACKAGE", "TEST_COMMON_PACKAGE");
@@ -6071,13 +6295,12 @@
         setCrossProfileAppsList("TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE");
         setVendorCrossProfileAppsList("TEST_VENDOR_DEFAULT_PACKAGE");
 
-        assertEquals(Sets.newSet(
-                        "TEST_PACKAGE", "TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE",
-                        "TEST_VENDOR_DEFAULT_PACKAGE"),
-                dpm.getAllCrossProfilePackages());
-
+        assertThat(dpm.getAllCrossProfilePackages()).containsExactly(
+                "TEST_PACKAGE", "TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE",
+                "TEST_VENDOR_DEFAULT_PACKAGE");
     }
 
+    @Test
     public void testGetAllCrossProfilePackages_whenSet_dpmsReinitialized_returnsCombinedSet()
             throws Exception {
         addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
@@ -6089,12 +6312,12 @@
         setVendorCrossProfileAppsList("TEST_VENDOR_DEFAULT_PACKAGE");
         initializeDpms();
 
-        assertEquals(Sets.newSet(
+        assertThat(dpm.getAllCrossProfilePackages()).containsExactly(
                 "TEST_PACKAGE", "TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE",
-                "TEST_VENDOR_DEFAULT_PACKAGE"),
-                dpm.getAllCrossProfilePackages());
+                "TEST_VENDOR_DEFAULT_PACKAGE");
     }
 
+    @Test
     public void testGetDefaultCrossProfilePackages_noPackagesSet_returnsEmpty() {
         setCrossProfileAppsList();
         setVendorCrossProfileAppsList();
@@ -6102,27 +6325,29 @@
         assertThat(dpm.getDefaultCrossProfilePackages()).isEmpty();
     }
 
+    @Test
     public void testGetDefaultCrossProfilePackages_packagesSet_returnsCombinedSet() {
         setCrossProfileAppsList("TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE");
         setVendorCrossProfileAppsList("TEST_VENDOR_DEFAULT_PACKAGE");
 
-        assertThat(dpm.getDefaultCrossProfilePackages()).isEqualTo(Sets.newSet(
-                "TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE", "TEST_VENDOR_DEFAULT_PACKAGE"
-        ));
+        assertThat(dpm.getDefaultCrossProfilePackages()).containsExactly(
+                "TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE", "TEST_VENDOR_DEFAULT_PACKAGE");
     }
 
+    @Test
     public void testSetCommonCriteriaMode_asDeviceOwner() throws Exception {
         setDeviceOwner();
 
-        assertFalse(dpm.isCommonCriteriaModeEnabled(admin1));
-        assertFalse(dpm.isCommonCriteriaModeEnabled(null));
+        assertThat(dpm.isCommonCriteriaModeEnabled(admin1)).isFalse();
+        assertThat(dpm.isCommonCriteriaModeEnabled(null)).isFalse();
 
         dpm.setCommonCriteriaModeEnabled(admin1, true);
 
-        assertTrue(dpm.isCommonCriteriaModeEnabled(admin1));
-        assertTrue(dpm.isCommonCriteriaModeEnabled(null));
+        assertThat(dpm.isCommonCriteriaModeEnabled(admin1)).isTrue();
+        assertThat(dpm.isCommonCriteriaModeEnabled(null)).isTrue();
     }
 
+    @Test
     public void testSetCommonCriteriaMode_asPoOfOrgOwnedDevice() throws Exception {
         final int managedProfileUserId = 15;
         final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
@@ -6130,15 +6355,16 @@
         configureProfileOwnerOfOrgOwnedDevice(admin1, managedProfileUserId);
         mContext.binder.callingUid = managedProfileAdminUid;
 
-        assertFalse(dpm.isCommonCriteriaModeEnabled(admin1));
-        assertFalse(dpm.isCommonCriteriaModeEnabled(null));
+        assertThat(dpm.isCommonCriteriaModeEnabled(admin1)).isFalse();
+        assertThat(dpm.isCommonCriteriaModeEnabled(null)).isFalse();
 
         dpm.setCommonCriteriaModeEnabled(admin1, true);
 
-        assertTrue(dpm.isCommonCriteriaModeEnabled(admin1));
-        assertTrue(dpm.isCommonCriteriaModeEnabled(null));
+        assertThat(dpm.isCommonCriteriaModeEnabled(admin1)).isTrue();
+        assertThat(dpm.isCommonCriteriaModeEnabled(null)).isTrue();
     }
 
+    @Test
     public void testCanProfileOwnerResetPasswordWhenLocked_nonDirectBootAwarePo()
             throws Exception {
         setDeviceEncryptionPerUser();
@@ -6146,30 +6372,33 @@
         setupPasswordResetToken();
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertFalse("po is not direct boot aware",
-                dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE));
+        assertWithMessage("po is not direct boot aware")
+                .that(dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE)).isFalse();
     }
 
+    @Test
     public void testCanProfileOwnerResetPasswordWhenLocked_noActiveToken() throws Exception {
         setDeviceEncryptionPerUser();
         setupProfileOwner();
         makeAdmin1DirectBootAware();
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertFalse("po doesn't have an active password reset token",
-                dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE));
+        assertWithMessage("po doesn't have an active password reset token")
+                .that(dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE)).isFalse();
     }
 
+    @Test
     public void testCanProfileOwnerResetPasswordWhenLocked_nonFbeDevice() throws Exception {
         setupProfileOwner();
         makeAdmin1DirectBootAware();
         setupPasswordResetToken();
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertFalse("device is not FBE",
-                dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE));
+        assertWithMessage("device is not FBE")
+                .that(dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE)).isFalse();
     }
 
+    @Test
     public void testCanProfileOwnerResetPasswordWhenLocked() throws Exception {
         setDeviceEncryptionPerUser();
         setupProfileOwner();
@@ -6177,8 +6406,8 @@
         setupPasswordResetToken();
 
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
-        assertTrue("direct boot aware po with active password reset token",
-                dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE));
+        assertWithMessage("direct boot aware po with active password reset token")
+                .that(dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE)).isTrue();
     }
 
     private void setupPasswordResetToken() {
@@ -6196,7 +6425,8 @@
                 .isEscrowTokenActive(eq(handle), eq(CALLER_USER_HANDLE)))
                 .thenReturn(true);
 
-        assertTrue("failed to activate token", dpm.isResetPasswordTokenActive(admin1));
+        assertWithMessage("failed to activate token").that(dpm.isResetPasswordTokenActive(admin1))
+                .isTrue();
     }
 
     private void makeAdmin1DirectBootAware()
@@ -6231,6 +6461,7 @@
                 .thenReturn(packages);
     }
 
+    @Test
     public void testSetAccountTypesWithManagementDisabledOnManagedProfile() throws Exception {
         setupProfileOwner();
 
@@ -6249,6 +6480,7 @@
         assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty();
     }
 
+    @Test
     public void testSetAccountTypesWithManagementDisabledOnOrgOwnedManagedProfile()
             throws Exception {
         final int managedProfileUserId = 15;
@@ -6284,6 +6516,7 @@
      * Tests the case when the user doesn't turn the profile on in time, verifies that the user is
      * warned with a notification and then the apps get suspended.
      */
+    @Test
     public void testMaximumProfileTimeOff_profileOffTimeExceeded() throws Exception {
         prepareMocksForSetMaximumProfileTimeOff();
 
@@ -6346,6 +6579,7 @@
     /**
      * Tests the case when the user turns the profile back on long before the deadline (> 1 day).
      */
+    @Test
     public void testMaximumProfileTimeOff_turnOnBeforeWarning() throws Exception {
         prepareMocksForSetMaximumProfileTimeOff();
 
@@ -6366,6 +6600,7 @@
     /**
      * Tests the case when the user turns the profile back on after the warning notification.
      */
+    @Test
     public void testMaximumProfileTimeOff_turnOnAfterWarning() throws Exception {
         prepareMocksForSetMaximumProfileTimeOff();
 
@@ -6395,6 +6630,7 @@
     /**
      * Tests the case when the user turns the profile back on when the apps are already suspended.
      */
+    @Test
     public void testMaximumProfileTimeOff_turnOnAfterDeadline() throws Exception {
         prepareMocksForSetMaximumProfileTimeOff();
 
@@ -6482,7 +6718,7 @@
     }
 
     private static Matcher<Notification> hasExtra(String... extras) {
-        assertEquals("Odd number of extra key-values", 0, extras.length % 2);
+        assertWithMessage("Odd number of extra key-values").that(extras.length % 2).isEqualTo(0);
         return new BaseMatcher<Notification>() {
             @Override
             public boolean matches(Object item) {
@@ -6520,17 +6756,17 @@
         // To simulate a reboot, we just reinitialize dpms and call systemReady
         initializeDpms();
 
-        assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
-        assertFalse(dpm.isDeviceOwnerApp(adminAnotherPackage.getPackageName()));
-        assertFalse(dpm.isAdminActive(adminAnotherPackage));
-        assertTrue(dpm.isAdminActive(admin1));
-        assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
-        assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+        assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue();
+        assertThat(dpm.isDeviceOwnerApp(adminAnotherPackage.getPackageName())).isFalse();
+        assertThat(dpm.isAdminActive(adminAnotherPackage)).isFalse();
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
+        assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isTrue();
+        assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
 
-        assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
-        assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
-        assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
-        assertFalse(getMockTransferMetadataManager().metadataFileExists());
+        assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isTrue();
+        assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
+        assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+        assertThat(getMockTransferMetadataManager().metadataFileExists()).isFalse();
 
         mServiceContext.binder.restoreCallingIdentity(ident);
     }
@@ -6547,12 +6783,12 @@
         // To simulate a reboot, we just reinitialize dpms and call systemReady
         initializeDpms();
 
-        assertTrue(dpm.isProfileOwnerApp(admin1.getPackageName()));
-        assertTrue(dpm.isAdminActive(admin1));
-        assertFalse(dpm.isProfileOwnerApp(adminAnotherPackage.getPackageName()));
-        assertFalse(dpm.isAdminActive(adminAnotherPackage));
-        assertEquals(dpm.getProfileOwnerAsUser(CALLER_USER_HANDLE), admin1);
-        assertFalse(getMockTransferMetadataManager().metadataFileExists());
+        assertThat(dpm.isProfileOwnerApp(admin1.getPackageName())).isTrue();
+        assertThat(dpm.isAdminActive(admin1)).isTrue();
+        assertThat(dpm.isProfileOwnerApp(adminAnotherPackage.getPackageName())).isFalse();
+        assertThat(dpm.isAdminActive(adminAnotherPackage)).isFalse();
+        assertThat(admin1).isEqualTo(dpm.getProfileOwnerAsUser(CALLER_USER_HANDLE));
+        assertThat(getMockTransferMetadataManager().metadataFileExists()).isFalse();
     }
 
     private void writeFakeTransferMetadataFile(int callerUserHandle, String adminType) {
@@ -6597,8 +6833,8 @@
     }
 
     private void assertProvisioningAllowed(String action, boolean expected) {
-        assertEquals("isProvisioningAllowed(" + action + ") returning unexpected result", expected,
-                dpm.isProvisioningAllowed(action));
+        assertWithMessage("isProvisioningAllowed(%s) returning unexpected result", action)
+                .that(dpm.isProvisioningAllowed(action)).isEqualTo(expected);
     }
 
     private void assertProvisioningAllowed(String action, boolean expected, String packageName,
@@ -6622,9 +6858,9 @@
 
     private void assertCheckProvisioningPreCondition(
             String action, String packageName, int provisioningCondition) {
-        assertEquals("checkProvisioningPreCondition("
-                        + action + ", " + packageName + ") returning unexpected result",
-                provisioningCondition, dpm.checkProvisioningPreCondition(action, packageName));
+        assertWithMessage("checkProvisioningPreCondition(%s, %s) returning unexpected result",
+                action, packageName).that(dpm.checkProvisioningPreCondition(action, packageName))
+                        .isEqualTo(provisioningCondition);
     }
 
     /**
@@ -6642,7 +6878,7 @@
         mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
         setUpPackageManagerForFakeAdmin(admin, adminUid, copyFromAdmin);
         dpm.setActiveAdmin(admin, false, userId);
-        assertTrue(dpm.setProfileOwner(admin, null, userId));
+        assertThat(dpm.setProfileOwner(admin, null, userId)).isTrue();
         mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
index 41d54e9..81570a1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
@@ -16,6 +16,8 @@
 
 package com.android.server.devicepolicy;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -35,18 +37,28 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.UserHandle;
-import android.test.AndroidTestCase;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Before;
 
 import java.io.InputStream;
 import java.util.List;
 
-public abstract class DpmTestBase extends AndroidTestCase {
+/**
+ * Temporary copy of DpmTestBase using JUnit 4 - once all tests extend it, it should be renamed
+ * back to DpmTestBase (with the temporary methods removed.
+ *
+ */
+public abstract class DpmTestBase {
+
     public static final String TAG = "DpmTest";
 
-    protected Context mRealTestContext;
+    protected final Context mRealTestContext = InstrumentationRegistry.getTargetContext();
     protected DpmMockContext mMockContext;
     private MockSystemServices mServices;
 
+    // Attributes below are public so they don't need to be prefixed with m
     public ComponentName admin1;
     public ComponentName admin2;
     public ComponentName admin3;
@@ -54,12 +66,8 @@
     public ComponentName adminNoPerm;
     public ComponentName delegateCertInstaller;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        mRealTestContext = super.getContext();
-
+    @Before
+    public void setFixtures() throws Exception {
         mServices = new MockSystemServices(mRealTestContext, "test-data");
         mMockContext = new DpmMockContext(mServices, mRealTestContext);
 
@@ -74,8 +82,7 @@
         mockSystemPropertiesToReturnDefault();
     }
 
-    @Override
-    public DpmMockContext getContext() {
+    protected DpmMockContext getContext() {
         return mMockContext;
     }
 
@@ -136,20 +143,15 @@
         final PackageInfo pi = DpmTestUtils.cloneParcelable(
                 mRealTestContext.getPackageManager().getPackageInfo(
                         mRealTestContext.getPackageName(), 0));
-        assertTrue(pi.applicationInfo.flags != 0);
+        assertThat(pi.applicationInfo.flags).isNotEqualTo(0);
 
         if (ai != null) {
             pi.applicationInfo = ai;
         }
 
-        doReturn(pi).when(mServices.ipackageManager).getPackageInfo(
-                eq(packageName),
-                eq(0),
-                eq(userId));
+        doReturn(pi).when(mServices.ipackageManager).getPackageInfo(packageName, 0, userId);
 
-        doReturn(ai.uid).when(mServices.packageManager).getPackageUidAsUser(
-                eq(packageName),
-                eq(userId));
+        doReturn(ai.uid).when(mServices.packageManager).getPackageUidAsUser(packageName, userId);
     }
 
     protected void markDelegatedCertInstallerAsInstalled() throws Exception {
@@ -230,8 +232,8 @@
                 mRealTestContext.getPackageManager().queryBroadcastReceivers(
                         resolveIntent,
                         PackageManager.GET_META_DATA);
-        assertNotNull(realResolveInfo);
-        assertEquals(1, realResolveInfo.size());
+        assertThat(realResolveInfo).isNotNull();
+        assertThat(realResolveInfo).hasSize(1);
 
         // We need to change AI, so set a clone.
         realResolveInfo.set(0, DpmTestUtils.cloneParcelable(realResolveInfo.get(0)));
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/FactoryResetProtectionPolicyTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/FactoryResetProtectionPolicyTest.java
index e8818a3..3aa5a80 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/FactoryResetProtectionPolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/FactoryResetProtectionPolicyTest.java
@@ -16,8 +16,8 @@
 
 package com.android.server.devicepolicy;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -100,7 +100,7 @@
         ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new InputStreamReader(inStream));
-        assertEquals(XmlPullParser.START_TAG, parser.next());
+        assertThat(parser.next()).isEqualTo(XmlPullParser.START_TAG);
 
         assertPoliciesAreEqual(policy, policy.readFromXml(parser));
     }
@@ -114,7 +114,7 @@
         parser.setInput(new InputStreamReader(inStream));
 
         // If deserialization fails, then null is returned.
-        assertNull(policy.readFromXml(parser));
+        assertThat(policy.readFromXml(parser)).isNull();
     }
 
     private ByteArrayOutputStream serialize(FactoryResetProtectionPolicy policy)
@@ -133,17 +133,17 @@
 
     private void assertPoliciesAreEqual(FactoryResetProtectionPolicy expectedPolicy,
             FactoryResetProtectionPolicy actualPolicy) {
-        assertEquals(expectedPolicy.isFactoryResetProtectionEnabled(),
-                actualPolicy.isFactoryResetProtectionEnabled());
+        assertThat(actualPolicy.isFactoryResetProtectionEnabled())
+                .isEqualTo(expectedPolicy.isFactoryResetProtectionEnabled());
         assertAccountsAreEqual(expectedPolicy.getFactoryResetProtectionAccounts(),
                 actualPolicy.getFactoryResetProtectionAccounts());
     }
 
     private void assertAccountsAreEqual(List<String> expectedAccounts,
             List<String> actualAccounts) {
-        assertEquals(expectedAccounts.size(), actualAccounts.size());
+        assertThat(actualAccounts.size()).isEqualTo(expectedAccounts.size());
         for (int i = 0; i < expectedAccounts.size(); i++) {
-            assertEquals(expectedAccounts.get(i), actualAccounts.get(i));
+            assertThat(actualAccounts.get(i)).isEqualTo(expectedAccounts.get(i));
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
index c698312..7506dd4 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
@@ -17,6 +17,9 @@
 
 import static com.android.server.devicepolicy.NetworkLoggingHandler.LOG_NETWORK_EVENT_MSG;
 
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.spy;
@@ -37,8 +40,9 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.server.LocalServices;
-import com.android.server.SystemService;
 
+import org.junit.Before;
+import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 
 import java.util.List;
@@ -50,9 +54,8 @@
     private DpmMockContext mSpiedDpmMockContext;
     private DevicePolicyManagerServiceTestable mDpmTestable;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws Exception {
         mSpiedDpmMockContext = spy(mMockContext);
         mSpiedDpmMockContext.callerPermissions.add(
                 android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -64,6 +67,7 @@
         mDpmTestable.setActiveAdmin(admin1, true, DpmMockContext.CALLER_USER_HANDLE);
     }
 
+    @Test
     public void testNetworkEventId_monotonicallyIncreasing() throws Exception {
         // GIVEN the handler has not processed any events.
         long startingId = 0;
@@ -72,17 +76,20 @@
         List<NetworkEvent> events = fillHandlerWithFullBatchOfEvents(startingId);
 
         // THEN the events are in a batch.
-        assertTrue("Batch not at the returned token.",
-                events != null && events.size() == MAX_EVENTS_PER_BATCH);
+        assertWithMessage("Batch not at the returned token.").that(events).isNotNull();
+        assertWithMessage("Batch not at the returned token.").that(events)
+                .hasSize(MAX_EVENTS_PER_BATCH);
+
         // THEN event ids are monotonically increasing.
         long expectedId = startingId;
         for (int i = 0; i < MAX_EVENTS_PER_BATCH; i++) {
-            assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
-                    events.get(i).getId());
+            assertWithMessage("At index %s, the event has the wrong id.", i)
+                    .that(events.get(i).getId()).isEqualTo(expectedId);
             expectedId++;
         }
     }
 
+    @Test
     public void testNetworkEventId_wrapsAround() throws Exception {
         // GIVEN the handler has almost processed Long.MAX_VALUE events.
         int gap = 5;
@@ -92,24 +99,25 @@
         List<NetworkEvent> events = fillHandlerWithFullBatchOfEvents(startingId);
 
         // THEN the events are in a batch.
-        assertTrue("Batch not at the returned token.",
-                events != null && events.size() == MAX_EVENTS_PER_BATCH);
+        assertWithMessage("Batch not at the returned token.").that(events).isNotNull();
+        assertWithMessage("Batch not at the returned token.").that(events)
+                .hasSize(MAX_EVENTS_PER_BATCH);
         // THEN event ids are monotonically increasing.
         long expectedId = startingId;
         for (int i = 0; i < gap; i++) {
-            assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
-                    events.get(i).getId());
+            assertWithMessage("At index %s, the event has the wrong id.", i)
+                    .that(events.get(i).getId()).isEqualTo(expectedId);
             expectedId++;
         }
         // THEN event ids are reset when the id reaches the maximum possible value.
-        assertEquals("Event was not assigned the maximum id value.", Long.MAX_VALUE,
-                events.get(gap).getId());
-        assertEquals("Event id was not reset.", 0, events.get(gap + 1).getId());
+        assertWithMessage("Event was not assigned the maximum id value.")
+                .that(events.get(gap).getId()).isEqualTo(Long.MAX_VALUE);
+        assertWithMessage("Event id was not reset.").that(events.get(gap + 1).getId()).isEqualTo(0);
         // THEN event ids are monotonically increasing.
         expectedId = 0;
         for (int i = gap + 1; i < MAX_EVENTS_PER_BATCH; i++) {
-            assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
-                    events.get(i).getId());
+            assertWithMessage("At index %s, the event has the wrong id.", i)
+                    .that(events.get(i).getId()).isEqualTo(expectedId);
             expectedId++;
         }
     }
@@ -134,8 +142,8 @@
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mSpiedDpmMockContext).sendBroadcastAsUser(intentCaptor.capture(),
                 any(UserHandle.class));
-        assertEquals(intentCaptor.getValue().getAction(),
-                DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE);
+        assertThat(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE)
+                .isEqualTo(intentCaptor.getValue().getAction());
         long token = intentCaptor.getValue().getExtras().getLong(
                 DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, 0);
         return handler.retrieveFullLogBatch(token);
@@ -144,6 +152,7 @@
     /**
      * Test parceling and unparceling of a ConnectEvent.
      */
+    @Test
     public void testConnectEventParceling() {
         ConnectEvent event = new ConnectEvent("127.0.0.1", 80, "com.android.whateverdude", 100000);
         event.setId(5L);
@@ -152,16 +161,17 @@
         p.setDataPosition(0);
         ConnectEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
         p.recycle();
-        assertEquals(event.getInetAddress(), unparceledEvent.getInetAddress());
-        assertEquals(event.getPort(), unparceledEvent.getPort());
-        assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
-        assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
-        assertEquals(event.getId(), unparceledEvent.getId());
+        assertThat(unparceledEvent.getInetAddress()).isEqualTo(event.getInetAddress());
+        assertThat(unparceledEvent.getPort()).isEqualTo(event.getPort());
+        assertThat(unparceledEvent.getPackageName()).isEqualTo(event.getPackageName());
+        assertThat(unparceledEvent.getTimestamp()).isEqualTo(event.getTimestamp());
+        assertThat(unparceledEvent.getId()).isEqualTo(event.getId());
     }
 
     /**
      * Test parceling and unparceling of a DnsEvent.
      */
+    @Test
     public void testDnsEventParceling() {
         DnsEvent event = new DnsEvent("d.android.com", new String[]{"192.168.0.1", "127.0.0.1"}, 2,
                 "com.android.whateverdude", 100000);
@@ -171,13 +181,15 @@
         p.setDataPosition(0);
         DnsEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
         p.recycle();
-        assertEquals(event.getHostname(), unparceledEvent.getHostname());
-        assertEquals(event.getInetAddresses().get(0), unparceledEvent.getInetAddresses().get(0));
-        assertEquals(event.getInetAddresses().get(1), unparceledEvent.getInetAddresses().get(1));
-        assertEquals(event.getTotalResolvedAddressCount(),
-                unparceledEvent.getTotalResolvedAddressCount());
-        assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
-        assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
-        assertEquals(event.getId(), unparceledEvent.getId());
+        assertThat(unparceledEvent.getHostname()).isEqualTo(event.getHostname());
+        assertThat(unparceledEvent.getInetAddresses().get(0))
+                .isEqualTo(event.getInetAddresses().get(0));
+        assertThat(unparceledEvent.getInetAddresses().get(1))
+                .isEqualTo(event.getInetAddresses().get(1));
+        assertThat(unparceledEvent.getTotalResolvedAddressCount())
+                .isEqualTo(event.getTotalResolvedAddressCount());
+        assertThat(unparceledEvent.getPackageName()).isEqualTo(event.getPackageName());
+        assertThat(unparceledEvent.getTimestamp()).isEqualTo(event.getTimestamp());
+        assertThat(unparceledEvent.getId()).isEqualTo(event.getId());
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
index a3cc915..24e226a 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
@@ -20,6 +20,9 @@
 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
 
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.when;
 
@@ -32,16 +35,17 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
-import android.test.AndroidTestCase;
 import android.test.mock.MockPackageManager;
 import android.view.inputmethod.InputMethodInfo;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.R;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -51,18 +55,23 @@
 import java.util.List;
 import java.util.Set;
 
-public class OverlayPackagesProviderTest extends AndroidTestCase {
+/**
+ * Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.OwnersTest}
+ *
+ */
+@RunWith(AndroidJUnit4.class)
+public class OverlayPackagesProviderTest {
     private static final String TEST_DPC_PACKAGE_NAME = "dpc.package.name";
     private static final ComponentName TEST_MDM_COMPONENT_NAME = new ComponentName(
             TEST_DPC_PACKAGE_NAME, "pc.package.name.DeviceAdmin");
     private static final int TEST_USER_ID = 123;
 
-    private @Mock
-    Resources mResources;
-    @Mock
-    private OverlayPackagesProvider.Injector mInjector;
-    private @Mock
-    Context mTestContext;
+    private @Mock Resources mResources;
+
+    private @Mock OverlayPackagesProvider.Injector mInjector;
+    private @Mock Context mTestContext;
     private Resources mRealResources;
 
     private FakePackageManager mPackageManager;
@@ -256,12 +265,12 @@
         ArrayList<String> required = getStringArrayInRealResources(requiredId);
         ArrayList<String> disallowed = getStringArrayInRealResources(disallowedId);
         required.retainAll(disallowed);
-        assertTrue(required.isEmpty());
+        assertThat(required.isEmpty()).isTrue();
     }
 
     private void verifyAppsAreNonRequired(String action, String... appArray) {
-        assertEquals(setFromArray(appArray),
-                mHelper.getNonRequiredApps(TEST_MDM_COMPONENT_NAME, TEST_USER_ID, action));
+        assertThat(mHelper.getNonRequiredApps(TEST_MDM_COMPONENT_NAME, TEST_USER_ID, action))
+                .containsExactlyElementsIn(setFromArray(appArray));
     }
 
     private void setRequiredAppsManagedDevice(String... apps) {
@@ -348,19 +357,19 @@
     class FakePackageManager extends MockPackageManager {
         @Override
         public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) {
-            assertTrue("Expected an intent with action ACTION_MAIN",
-                    Intent.ACTION_MAIN.equals(intent.getAction()));
-            assertEquals("Expected an intent with category CATEGORY_LAUNCHER",
-                    setFromArray(Intent.CATEGORY_LAUNCHER), intent.getCategories());
-            assertTrue("Expected the flag MATCH_UNINSTALLED_PACKAGES",
-                    (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0);
-            assertTrue("Expected the flag MATCH_DISABLED_COMPONENTS",
-                    (flags & PackageManager.MATCH_DISABLED_COMPONENTS) != 0);
-            assertTrue("Expected the flag MATCH_DIRECT_BOOT_AWARE",
-                    (flags & PackageManager.MATCH_DIRECT_BOOT_AWARE) != 0);
-            assertTrue("Expected the flag MATCH_DIRECT_BOOT_UNAWARE",
-                    (flags & PackageManager.MATCH_DIRECT_BOOT_UNAWARE) != 0);
-            assertEquals(userId, TEST_USER_ID);
+            assertWithMessage("Expected an intent with action ACTION_MAIN")
+                    .that(Intent.ACTION_MAIN.equals(intent.getAction())).isTrue();
+            assertWithMessage("Expected an intent with category CATEGORY_LAUNCHER")
+                    .that(intent.getCategories()).containsExactly(Intent.CATEGORY_LAUNCHER);
+            assertWithMessage("Expected the flag MATCH_UNINSTALLED_PACKAGES")
+                    .that((flags & PackageManager.MATCH_UNINSTALLED_PACKAGES)).isNotEqualTo(0);
+            assertWithMessage("Expected the flag MATCH_DISABLED_COMPONENTS")
+                    .that((flags & PackageManager.MATCH_DISABLED_COMPONENTS)).isNotEqualTo(0);
+            assertWithMessage("Expected the flag MATCH_DIRECT_BOOT_AWARE")
+                    .that((flags & PackageManager.MATCH_DIRECT_BOOT_AWARE)).isNotEqualTo(0);
+            assertWithMessage("Expected the flag MATCH_DIRECT_BOOT_UNAWARE")
+                    .that((flags & PackageManager.MATCH_DIRECT_BOOT_UNAWARE)).isNotEqualTo(0);
+            assertThat(TEST_USER_ID).isEqualTo(userId);
             List<ResolveInfo> result = new ArrayList<>();
             if (mSystemAppsWithLauncher == null) {
                 return result;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
index 5899bb0..bfe183c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
@@ -16,25 +16,32 @@
 
 package com.android.server.devicepolicy;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import android.content.ComponentName;
 import android.os.UserHandle;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 /**
  * Tests for the DeviceOwner object that saves & loads device and policy owner information.
- * run this test with:
- m FrameworksServicesTests &&
- adb install \
-   -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
- adb shell am instrument -e class com.android.server.devicepolicy.OwnersTest \
-   -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
-
- (mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
+ *
+ * <p>Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.OwnersTest}
+ *
  */
 @SmallTest
+@RunWith(AndroidJUnit4.class)
 public class OwnersTest extends DpmTestBase {
+
+    @Test
     public void testUpgrade01() throws Exception {
         getServices().addUsers(10, 11, 20, 21);
 
@@ -48,26 +55,26 @@
             owners.load();
 
             // The legacy file should be removed.
-            assertFalse(owners.getLegacyConfigFile().exists());
+            assertThat(owners.getLegacyConfigFile().exists()).isFalse();
 
             // File was empty, so no new files should be created.
-            assertFalse(owners.getDeviceOwnerFile().exists());
+            assertThat(owners.getDeviceOwnerFile().exists()).isFalse();
 
-            assertFalse(owners.getProfileOwnerFile(10).exists());
-            assertFalse(owners.getProfileOwnerFile(11).exists());
-            assertFalse(owners.getProfileOwnerFile(20).exists());
-            assertFalse(owners.getProfileOwnerFile(21).exists());
+            assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(21).exists()).isFalse();
 
-            assertFalse(owners.hasDeviceOwner());
-            assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
-            assertNull(owners.getSystemUpdatePolicy());
-            assertEquals(0, owners.getProfileOwnerKeys().size());
+            assertThat(owners.hasDeviceOwner()).isFalse();
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getSystemUpdatePolicy()).isNull();
+            assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
-            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
         }
 
         // Then re-read and check.
@@ -75,19 +82,20 @@
             final OwnersTestable owners = new OwnersTestable(getServices());
             owners.load();
 
-            assertFalse(owners.hasDeviceOwner());
-            assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
-            assertNull(owners.getSystemUpdatePolicy());
-            assertEquals(0, owners.getProfileOwnerKeys().size());
+            assertThat(owners.hasDeviceOwner()).isFalse();
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getSystemUpdatePolicy()).isNull();
+            assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
-            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
         }
     }
 
+    @Test
     public void testUpgrade02() throws Exception {
         getServices().addUsers(10, 11, 20, 21);
 
@@ -101,28 +109,28 @@
             owners.load();
 
             // The legacy file should be removed.
-            assertFalse(owners.getLegacyConfigFile().exists());
+            assertThat(owners.getLegacyConfigFile().exists()).isFalse();
 
-            assertTrue(owners.getDeviceOwnerFile().exists()); // TODO Check content
+            assertThat(owners.getDeviceOwnerFile().exists()).isTrue(); // TODO Check content
 
-            assertFalse(owners.getProfileOwnerFile(10).exists());
-            assertFalse(owners.getProfileOwnerFile(11).exists());
-            assertFalse(owners.getProfileOwnerFile(20).exists());
-            assertFalse(owners.getProfileOwnerFile(21).exists());
+            assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(21).exists()).isFalse();
 
-            assertTrue(owners.hasDeviceOwner());
-            assertEquals(null, owners.getDeviceOwnerName());
-            assertEquals("com.google.android.testdpc", owners.getDeviceOwnerPackageName());
-            assertEquals(UserHandle.USER_SYSTEM, owners.getDeviceOwnerUserId());
+            assertThat(owners.hasDeviceOwner()).isTrue();
+            assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
+            assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
 
-            assertNull(owners.getSystemUpdatePolicy());
-            assertEquals(0, owners.getProfileOwnerKeys().size());
+            assertThat(owners.getSystemUpdatePolicy()).isNull();
+            assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
-            assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
         }
 
         // Then re-read and check.
@@ -130,22 +138,23 @@
             final OwnersTestable owners = new OwnersTestable(getServices());
             owners.load();
 
-            assertTrue(owners.hasDeviceOwner());
-            assertEquals(null, owners.getDeviceOwnerName());
-            assertEquals("com.google.android.testdpc", owners.getDeviceOwnerPackageName());
-            assertEquals(UserHandle.USER_SYSTEM, owners.getDeviceOwnerUserId());
+            assertThat(owners.hasDeviceOwner()).isTrue();
+            assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
+            assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
 
-            assertNull(owners.getSystemUpdatePolicy());
-            assertEquals(0, owners.getProfileOwnerKeys().size());
+            assertThat(owners.getSystemUpdatePolicy()).isNull();
+            assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
-            assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
         }
     }
 
+    @Test
     public void testUpgrade03() throws Exception {
         getServices().addUsers(10, 11, 20, 21);
 
@@ -159,36 +168,36 @@
             owners.load();
 
             // The legacy file should be removed.
-            assertFalse(owners.getLegacyConfigFile().exists());
+            assertThat(owners.getLegacyConfigFile().exists()).isFalse();
 
-            assertFalse(owners.getDeviceOwnerFile().exists());
+            assertThat(owners.getDeviceOwnerFile().exists()).isFalse();
 
-            assertTrue(owners.getProfileOwnerFile(10).exists());
-            assertTrue(owners.getProfileOwnerFile(11).exists());
-            assertFalse(owners.getProfileOwnerFile(20).exists());
-            assertFalse(owners.getProfileOwnerFile(21).exists());
+            assertThat(owners.getProfileOwnerFile(10).exists()).isTrue();
+            assertThat(owners.getProfileOwnerFile(11).exists()).isTrue();
+            assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(21).exists()).isFalse();
 
-            assertFalse(owners.hasDeviceOwner());
-            assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
-            assertNull(owners.getSystemUpdatePolicy());
+            assertThat(owners.hasDeviceOwner()).isFalse();
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getSystemUpdatePolicy()).isNull();
 
-            assertEquals(2, owners.getProfileOwnerKeys().size());
-            assertEquals(new ComponentName("com.google.android.testdpc",
-                            "com.google.android.testdpc.DeviceAdminReceiver0"),
-                    owners.getProfileOwnerComponent(10));
-            assertEquals("0", owners.getProfileOwnerName(10));
-            assertEquals("com.google.android.testdpc", owners.getProfileOwnerPackage(10));
+            assertThat(owners.getProfileOwnerKeys()).hasSize(2);
+            assertThat(owners.getProfileOwnerComponent(10))
+                    .isEqualTo(new ComponentName("com.google.android.testdpc",
+                            "com.google.android.testdpc.DeviceAdminReceiver0"));
+            assertThat(owners.getProfileOwnerName(10)).isEqualTo("0");
+            assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc");
 
-            assertEquals(new ComponentName("com.google.android.testdpc1", ""),
-                    owners.getProfileOwnerComponent(11));
-            assertEquals("1", owners.getProfileOwnerName(11));
-            assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
+            assertThat(owners.getProfileOwnerComponent(11))
+                    .isEqualTo(new ComponentName("com.google.android.testdpc1", ""));
+            assertThat(owners.getProfileOwnerName(11)).isEqualTo("1");
+            assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1");
 
-            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
         }
 
         // Then re-read and check.
@@ -196,27 +205,27 @@
             final OwnersTestable owners = new OwnersTestable(getServices());
             owners.load();
 
-            assertFalse(owners.hasDeviceOwner());
-            assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
-            assertNull(owners.getSystemUpdatePolicy());
+            assertThat(owners.hasDeviceOwner()).isFalse();
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getSystemUpdatePolicy()).isNull();
 
-            assertEquals(2, owners.getProfileOwnerKeys().size());
-            assertEquals(new ComponentName("com.google.android.testdpc",
-                            "com.google.android.testdpc.DeviceAdminReceiver0"),
-                    owners.getProfileOwnerComponent(10));
-            assertEquals("0", owners.getProfileOwnerName(10));
-            assertEquals("com.google.android.testdpc", owners.getProfileOwnerPackage(10));
+            assertThat(owners.getProfileOwnerKeys()).hasSize(2);
+            assertThat(owners.getProfileOwnerComponent(10))
+                    .isEqualTo(new ComponentName("com.google.android.testdpc",
+                            "com.google.android.testdpc.DeviceAdminReceiver0"));
+            assertThat(owners.getProfileOwnerName(10)).isEqualTo("0");
+            assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc");
 
-            assertEquals(new ComponentName("com.google.android.testdpc1", ""),
-                    owners.getProfileOwnerComponent(11));
-            assertEquals("1", owners.getProfileOwnerName(11));
-            assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
+            assertThat(owners.getProfileOwnerComponent(11))
+                    .isEqualTo(new ComponentName("com.google.android.testdpc1", ""));
+            assertThat(owners.getProfileOwnerName(11)).isEqualTo("1");
+            assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1");
 
-            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
         }
     }
 
@@ -224,6 +233,7 @@
      * Note this also tests {@link Owners#setDeviceOwnerUserRestrictionsMigrated()}
      * and {@link  Owners#setProfileOwnerUserRestrictionsMigrated(int)}.
      */
+    @Test
     public void testUpgrade04() throws Exception {
         getServices().addUsers(10, 11, 20, 21);
 
@@ -237,40 +247,40 @@
             owners.load();
 
             // The legacy file should be removed.
-            assertFalse(owners.getLegacyConfigFile().exists());
+            assertThat(owners.getLegacyConfigFile().exists()).isFalse();
 
-            assertTrue(owners.getDeviceOwnerFile().exists());
+            assertThat(owners.getDeviceOwnerFile().exists()).isTrue();
 
-            assertTrue(owners.getProfileOwnerFile(10).exists());
-            assertTrue(owners.getProfileOwnerFile(11).exists());
-            assertFalse(owners.getProfileOwnerFile(20).exists());
-            assertFalse(owners.getProfileOwnerFile(21).exists());
+            assertThat(owners.getProfileOwnerFile(10).exists()).isTrue();
+            assertThat(owners.getProfileOwnerFile(11).exists()).isTrue();
+            assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(21).exists()).isFalse();
 
-            assertTrue(owners.hasDeviceOwner());
-            assertEquals(null, owners.getDeviceOwnerName());
-            assertEquals("com.google.android.testdpc", owners.getDeviceOwnerPackageName());
-            assertEquals(UserHandle.USER_SYSTEM, owners.getDeviceOwnerUserId());
+            assertThat(owners.hasDeviceOwner()).isTrue();
+            assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
+            assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
 
-            assertNotNull(owners.getSystemUpdatePolicy());
-            assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
+            assertThat(owners.getSystemUpdatePolicy()).isNotNull();
+            assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
 
-            assertEquals(2, owners.getProfileOwnerKeys().size());
-            assertEquals(new ComponentName("com.google.android.testdpc",
-                            "com.google.android.testdpc.DeviceAdminReceiver0"),
-                    owners.getProfileOwnerComponent(10));
-            assertEquals("0", owners.getProfileOwnerName(10));
-            assertEquals("com.google.android.testdpc", owners.getProfileOwnerPackage(10));
+            assertThat(owners.getProfileOwnerKeys()).hasSize(2);
+            assertThat(owners.getProfileOwnerComponent(10))
+                    .isEqualTo(new ComponentName("com.google.android.testdpc",
+                            "com.google.android.testdpc.DeviceAdminReceiver0"));
+            assertThat(owners.getProfileOwnerName(10)).isEqualTo("0");
+            assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc");
 
-            assertEquals(new ComponentName("com.google.android.testdpc1", ""),
-                    owners.getProfileOwnerComponent(11));
-            assertEquals("1", owners.getProfileOwnerName(11));
-            assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
+            assertThat(owners.getProfileOwnerComponent(11))
+                    .isEqualTo(new ComponentName("com.google.android.testdpc1", ""));
+            assertThat(owners.getProfileOwnerName(11)).isEqualTo("1");
+            assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1");
 
-            assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
         }
 
         // Then re-read and check.
@@ -278,31 +288,31 @@
             final OwnersTestable owners = new OwnersTestable(getServices());
             owners.load();
 
-            assertTrue(owners.hasDeviceOwner());
-            assertEquals(null, owners.getDeviceOwnerName());
-            assertEquals("com.google.android.testdpc", owners.getDeviceOwnerPackageName());
-            assertEquals(UserHandle.USER_SYSTEM, owners.getDeviceOwnerUserId());
+            assertThat(owners.hasDeviceOwner()).isTrue();
+            assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
+            assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
 
-            assertNotNull(owners.getSystemUpdatePolicy());
-            assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
+            assertThat(owners.getSystemUpdatePolicy()).isNotNull();
+            assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
 
-            assertEquals(2, owners.getProfileOwnerKeys().size());
-            assertEquals(new ComponentName("com.google.android.testdpc",
-                            "com.google.android.testdpc.DeviceAdminReceiver0"),
-                    owners.getProfileOwnerComponent(10));
-            assertEquals("0", owners.getProfileOwnerName(10));
-            assertEquals("com.google.android.testdpc", owners.getProfileOwnerPackage(10));
+            assertThat(owners.getProfileOwnerKeys()).hasSize(2);
+            assertThat(owners.getProfileOwnerComponent(10))
+                    .isEqualTo(new ComponentName("com.google.android.testdpc",
+                            "com.google.android.testdpc.DeviceAdminReceiver0"));
+            assertThat(owners.getProfileOwnerName(10)).isEqualTo("0");
+            assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc");
 
-            assertEquals(new ComponentName("com.google.android.testdpc1", ""),
-                    owners.getProfileOwnerComponent(11));
-            assertEquals("1", owners.getProfileOwnerName(11));
-            assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
+            assertThat(owners.getProfileOwnerComponent(11))
+                    .isEqualTo(new ComponentName("com.google.android.testdpc1", ""));
+            assertThat(owners.getProfileOwnerName(11)).isEqualTo("1");
+            assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1");
 
-            assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
 
             owners.setDeviceOwnerUserRestrictionsMigrated();
         }
@@ -311,11 +321,11 @@
             final OwnersTestable owners = new OwnersTestable(getServices());
             owners.load();
 
-            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
 
             owners.setProfileOwnerUserRestrictionsMigrated(11);
         }
@@ -324,16 +334,17 @@
             final OwnersTestable owners = new OwnersTestable(getServices());
             owners.load();
 
-            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
 
             owners.setProfileOwnerUserRestrictionsMigrated(11);
         }
     }
 
+    @Test
     public void testUpgrade05() throws Exception {
         getServices().addUsers(10, 11, 20, 21);
 
@@ -347,27 +358,27 @@
             owners.load();
 
             // The legacy file should be removed.
-            assertFalse(owners.getLegacyConfigFile().exists());
+            assertThat(owners.getLegacyConfigFile().exists()).isFalse();
 
             // Note device initializer is no longer supported.  No need to write the DO file.
-            assertFalse(owners.getDeviceOwnerFile().exists());
+            assertThat(owners.getDeviceOwnerFile().exists()).isFalse();
 
-            assertFalse(owners.getProfileOwnerFile(10).exists());
-            assertFalse(owners.getProfileOwnerFile(11).exists());
-            assertFalse(owners.getProfileOwnerFile(20).exists());
+            assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
 
-            assertFalse(owners.hasDeviceOwner());
-            assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
+            assertThat(owners.hasDeviceOwner()).isFalse();
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
 
 
-            assertNull(owners.getSystemUpdatePolicy());
-            assertEquals(0, owners.getProfileOwnerKeys().size());
+            assertThat(owners.getSystemUpdatePolicy()).isNull();
+            assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
-            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
         }
 
         // Then re-read and check.
@@ -375,21 +386,22 @@
             final OwnersTestable owners = new OwnersTestable(getServices());
             owners.load();
 
-            assertFalse(owners.hasDeviceOwner());
-            assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
+            assertThat(owners.hasDeviceOwner()).isFalse();
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
 
 
-            assertNull(owners.getSystemUpdatePolicy());
-            assertEquals(0, owners.getProfileOwnerKeys().size());
+            assertThat(owners.getSystemUpdatePolicy()).isNull();
+            assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
-            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
         }
     }
 
+    @Test
     public void testUpgrade06() throws Exception {
         getServices().addUsers(10, 11, 20, 21);
 
@@ -403,26 +415,26 @@
             owners.load();
 
             // The legacy file should be removed.
-            assertFalse(owners.getLegacyConfigFile().exists());
+            assertThat(owners.getLegacyConfigFile().exists()).isFalse();
 
-            assertTrue(owners.getDeviceOwnerFile().exists());
+            assertThat(owners.getDeviceOwnerFile().exists()).isTrue();
 
-            assertFalse(owners.getProfileOwnerFile(10).exists());
-            assertFalse(owners.getProfileOwnerFile(11).exists());
-            assertFalse(owners.getProfileOwnerFile(20).exists());
+            assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
+            assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
 
-            assertFalse(owners.hasDeviceOwner());
-            assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
-            assertEquals(0, owners.getProfileOwnerKeys().size());
+            assertThat(owners.hasDeviceOwner()).isFalse();
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
-            assertNotNull(owners.getSystemUpdatePolicy());
-            assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
+            assertThat(owners.getSystemUpdatePolicy()).isNotNull();
+            assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
 
-            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
         }
 
         // Then re-read and check.
@@ -430,21 +442,22 @@
             final OwnersTestable owners = new OwnersTestable(getServices());
             owners.load();
 
-            assertFalse(owners.hasDeviceOwner());
-            assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
-            assertEquals(0, owners.getProfileOwnerKeys().size());
+            assertThat(owners.hasDeviceOwner()).isFalse();
+            assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+            assertThat(owners.getProfileOwnerKeys()).isEmpty();
 
-            assertNotNull(owners.getSystemUpdatePolicy());
-            assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
+            assertThat(owners.getSystemUpdatePolicy()).isNotNull();
+            assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
 
-            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
-            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+            assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+            assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
         }
     }
 
+    @Test
     public void testRemoveExistingFiles() throws Exception {
         getServices().addUsers(10, 11, 20, 21);
 
@@ -456,11 +469,11 @@
 
         owners.load();
 
-        assertFalse(owners.getLegacyConfigFile().exists());
+        assertThat(owners.getLegacyConfigFile().exists()).isFalse();
 
-        assertTrue(owners.getDeviceOwnerFile().exists());
-        assertTrue(owners.getProfileOwnerFile(10).exists());
-        assertTrue(owners.getProfileOwnerFile(11).exists());
+        assertThat(owners.getDeviceOwnerFile().exists()).isTrue();
+        assertThat(owners.getProfileOwnerFile(10).exists()).isTrue();
+        assertThat(owners.getProfileOwnerFile(11).exists()).isTrue();
 
         // Then clear all information and save.
         owners.clearDeviceOwner();
@@ -475,8 +488,8 @@
         owners.writeProfileOwner(21);
 
         // Now all files should be removed.
-        assertFalse(owners.getDeviceOwnerFile().exists());
-        assertFalse(owners.getProfileOwnerFile(10).exists());
-        assertFalse(owners.getProfileOwnerFile(11).exists());
+        assertThat(owners.getDeviceOwnerFile().exists()).isFalse();
+        assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
+        assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java
index 8dcf21f..6cefaeb 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2020 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.devicepolicy;
 
 import static android.app.admin.SecurityLog.TAG_ADB_SHELL_CMD;
@@ -11,6 +26,8 @@
 import static android.app.admin.SecurityLog.TAG_MEDIA_MOUNT;
 import static android.app.admin.SecurityLog.TAG_MEDIA_UNMOUNT;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import android.app.admin.SecurityLog.SecurityEvent;
 import android.os.Parcel;
 import android.os.UserHandle;
@@ -18,21 +35,37 @@
 import android.util.EventLog;
 import android.util.EventLog.Event;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import junit.framework.AssertionFailedError;
 
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * Tests for the DeviceOwner object that saves & loads device and policy owner information.
+ *
+ * <p>Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.SecurityEventTest}
+ *
+ */
+@RunWith(AndroidJUnit4.class)
 public class SecurityEventTest extends DpmTestBase {
 
+    @Test
     public void testSecurityEventId() throws Exception {
         SecurityEvent event = createEvent(() -> {
             EventLog.writeEvent(TAG_ADB_SHELL_CMD, 0);
         }, TAG_ADB_SHELL_CMD);
         event.setId(20);
-        assertEquals(20, event.getId());
+        assertThat(event.getId()).isEqualTo(20);
     }
 
+    @Test
     public void testSecurityEventParceling() throws Exception {
         // GIVEN an event.
         SecurityEvent event = createEvent(() -> {
@@ -45,12 +78,13 @@
         SecurityEvent unparceledEvent = p.readParcelable(SecurityEventTest.class.getClassLoader());
         p.recycle();
         // THEN the event state is preserved.
-        assertEquals(event.getTag(), unparceledEvent.getTag());
-        assertEquals(event.getData(), unparceledEvent.getData());
-        assertEquals(event.getTimeNanos(), unparceledEvent.getTimeNanos());
-        assertEquals(event.getId(), unparceledEvent.getId());
+        assertThat(unparceledEvent.getTag()).isEqualTo(event.getTag());
+        assertThat(unparceledEvent.getData()).isEqualTo(event.getData());
+        assertThat(unparceledEvent.getTimeNanos()).isEqualTo(event.getTimeNanos());
+        assertThat(unparceledEvent.getId()).isEqualTo(event.getId());
     }
 
+    @Test
     public void testSecurityEventRedaction() throws Exception {
         SecurityEvent event;
 
@@ -58,75 +92,75 @@
         event = createEvent(() -> {
             EventLog.writeEvent(TAG_ADB_SHELL_CMD, "command");
         }, TAG_ADB_SHELL_CMD);
-        assertFalse(TextUtils.isEmpty((String) event.getData()));
+        assertThat(TextUtils.isEmpty((String) event.getData())).isFalse();
 
         // TAG_MEDIA_MOUNT will have the volume label redacted (second data)
         event = createEvent(() -> {
             EventLog.writeEvent(TAG_MEDIA_MOUNT, new Object[] {"path", "label"});
         }, TAG_MEDIA_MOUNT);
-        assertFalse(TextUtils.isEmpty(event.getStringData(1)));
-        assertTrue(TextUtils.isEmpty(event.redact(0).getStringData(1)));
+        assertThat(TextUtils.isEmpty(event.getStringData(1))).isFalse();
+        assertThat(TextUtils.isEmpty(event.redact(0).getStringData(1))).isTrue();
 
         // TAG_MEDIA_UNMOUNT will have the volume label redacted (second data)
         event = createEvent(() -> {
             EventLog.writeEvent(TAG_MEDIA_UNMOUNT, new Object[] {"path", "label"});
         }, TAG_MEDIA_UNMOUNT);
-        assertFalse(TextUtils.isEmpty(event.getStringData(1)));
-        assertTrue(TextUtils.isEmpty(event.redact(0).getStringData(1)));
+        assertThat(TextUtils.isEmpty(event.getStringData(1))).isFalse();
+        assertThat(TextUtils.isEmpty(event.redact(0).getStringData(1))).isTrue();
 
         // TAG_APP_PROCESS_START will be fully redacted if user does not match
         event = createEvent(() -> {
             EventLog.writeEvent(TAG_APP_PROCESS_START, new Object[] {"process", 12345L,
                     UserHandle.getUid(10, 123), 456, "seinfo", "hash"});
         }, TAG_APP_PROCESS_START);
-        assertNotNull(event.redact(10));
-        assertNull(event.redact(11));
+        assertThat(event.redact(10)).isNotNull();
+        assertThat(event.redact(11)).isNull();
 
         // TAG_CERT_AUTHORITY_INSTALLED will be fully redacted if user does not match
         event = createEvent(() -> {
             EventLog.writeEvent(TAG_CERT_AUTHORITY_INSTALLED, new Object[] {1, "subject", 10});
         }, TAG_CERT_AUTHORITY_INSTALLED);
-        assertNotNull(event.redact(10));
-        assertNull(event.redact(11));
+        assertThat(event.redact(10)).isNotNull();
+        assertThat(event.redact(11)).isNull();
 
         // TAG_CERT_AUTHORITY_REMOVED will be fully redacted if user does not match
         event = createEvent(() -> {
             EventLog.writeEvent(TAG_CERT_AUTHORITY_REMOVED, new Object[] {1, "subject", 20});
         }, TAG_CERT_AUTHORITY_REMOVED);
-        assertNotNull(event.redact(20));
-        assertNull(event.redact(0));
+        assertThat(event.redact(20)).isNotNull();
+        assertThat(event.redact(0)).isNull();
 
         // TAG_KEY_GENERATED will be fully redacted if user does not match
         event = createEvent(() -> {
             EventLog.writeEvent(TAG_KEY_GENERATED,
                     new Object[] {1, "alias", UserHandle.getUid(0, 123)});
         }, TAG_KEY_GENERATED);
-        assertNotNull(event.redact(0));
-        assertNull(event.redact(10));
+        assertThat(event.redact(0)).isNotNull();
+        assertThat(event.redact(10)).isNull();
 
         // TAG_KEY_IMPORT will be fully redacted if user does not match
         event = createEvent(() -> {
             EventLog.writeEvent(TAG_KEY_IMPORT,
                     new Object[] {1, "alias", UserHandle.getUid(1, 123)});
         }, TAG_KEY_IMPORT);
-        assertNotNull(event.redact(1));
-        assertNull(event.redact(10));
+        assertThat(event.redact(1)).isNotNull();
+        assertThat(event.redact(10)).isNull();
 
         // TAG_KEY_DESTRUCTION will be fully redacted if user does not match
         event = createEvent(() -> {
             EventLog.writeEvent(TAG_KEY_DESTRUCTION,
                     new Object[] {1, "alias", UserHandle.getUid(2, 123)});
         }, TAG_KEY_DESTRUCTION);
-        assertNotNull(event.redact(2));
-        assertNull(event.redact(10));
+        assertThat(event.redact(2)).isNotNull();
+        assertThat(event.redact(10)).isNull();
 
         // TAG_KEY_INTEGRITY_VIOLATION will be fully redacted if user does not match
         event = createEvent(() -> {
             EventLog.writeEvent(TAG_KEY_INTEGRITY_VIOLATION,
                     new Object[] {"alias", UserHandle.getUid(2, 123)});
         }, TAG_KEY_INTEGRITY_VIOLATION);
-        assertNotNull(event.redact(2));
-        assertNull(event.redact(10));
+        assertThat(event.redact(2)).isNotNull();
+        assertThat(event.redact(10)).isNull();
 
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
index e51859b..0a9aad7 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
@@ -21,8 +21,9 @@
 import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE;
 import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_NEW_FREEZE_PERIOD_TOO_LONG;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import static org.junit.Assert.fail;
 
 import android.app.admin.FreezePeriod;
@@ -53,10 +54,12 @@
 
 /**
  * Unit tests for {@link android.app.admin.SystemUpdatePolicy}.
- * Throughout this test, we use "MM-DD" format to denote dates without year.
  *
- * atest com.android.server.devicepolicy.SystemUpdatePolicyTest
- * runtest -c com.android.server.devicepolicy.SystemUpdatePolicyTest frameworks-services
+ * <p>NOTE: Throughout this test, we use {@code "MM-DD"} format to denote dates without year.
+ *
+ * <p>Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.SystemUpdatePolicyTest}
  */
 @RunWith(AndroidJUnit4.class)
 public final class SystemUpdatePolicyTest {
@@ -224,37 +227,37 @@
 
     @Test
     public void testDistanceWithoutLeapYear() {
-        assertEquals(364, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2016, 12, 31), LocalDate.of(2016, 1, 1)));
-        assertEquals(365, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2017, 1, 1), LocalDate.of(2016, 1, 1)));
-        assertEquals(365, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2017, 2, 28), LocalDate.of(2016, 2, 29)));
-        assertEquals(-365, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2016, 1, 1), LocalDate.of(2017, 1, 1)));
-        assertEquals(1, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 29)));
-        assertEquals(1, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 28)));
-        assertEquals(0, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2016, 2, 29), LocalDate.of(2016, 2, 28)));
-        assertEquals(0, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2016, 2, 28), LocalDate.of(2016, 2, 28)));
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2016, 12, 31), LocalDate.of(2016, 1, 1))).isEqualTo(364);
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2017, 1, 1), LocalDate.of(2016, 1, 1))).isEqualTo(365);
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2017, 2, 28), LocalDate.of(2016, 2, 29))).isEqualTo(365);
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2016, 1, 1), LocalDate.of(2017, 1, 1))).isEqualTo(-365);
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 29))).isEqualTo(1);
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 28))).isEqualTo(1);
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2016, 2, 29), LocalDate.of(2016, 2, 28))).isEqualTo(0);
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2016, 2, 28), LocalDate.of(2016, 2, 28))).isEqualTo(0);
 
-        assertEquals(59, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2016, 3, 1), LocalDate.of(2016, 1, 1)));
-        assertEquals(59, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2017, 3, 1), LocalDate.of(2017, 1, 1)));
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2016, 3, 1), LocalDate.of(2016, 1, 1))).isEqualTo(59);
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2017, 3, 1), LocalDate.of(2017, 1, 1))).isEqualTo(59);
 
-        assertEquals(365 * 40, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2040, 1, 1), LocalDate.of(2000, 1, 1)));
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2040, 1, 1), LocalDate.of(2000, 1, 1))).isEqualTo(365 * 40);
 
-        assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2019, 3, 1), LocalDate.of(2017, 3, 1)));
-        assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2018, 3, 1), LocalDate.of(2016, 3, 1)));
-        assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
-                LocalDate.of(2017, 3, 1), LocalDate.of(2015, 3, 1)));
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2019, 3, 1), LocalDate.of(2017, 3, 1))).isEqualTo(365 * 2);
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2018, 3, 1), LocalDate.of(2016, 3, 1))).isEqualTo(365 * 2);
+        assertThat(FreezePeriod.distanceWithoutLeapYear(
+        LocalDate.of(2017, 3, 1), LocalDate.of(2015, 3, 1))).isEqualTo(365 * 2);
 
     }
 
@@ -395,8 +398,8 @@
 
     private void assertInstallationOption(int expectedType, long expectedTime, long now,
             SystemUpdatePolicy p) {
-        assertEquals(expectedType, p.getInstallationOptionAt(now).getType());
-        assertEquals(expectedTime, p.getInstallationOptionAt(now).getEffectiveTime());
+        assertThat(p.getInstallationOptionAt(now).getType()).isEqualTo(expectedType);
+        assertThat(p.getInstallationOptionAt(now).getEffectiveTime()).isEqualTo(expectedTime);
     }
 
     private void testFreezePeriodsSucceeds(String...dates) throws Exception {
@@ -410,8 +413,8 @@
             setFreezePeriods(p, dates);
             fail("Invalid periods (" + expectedError + ") not flagged: " + String.join(" ", dates));
         } catch (SystemUpdatePolicy.ValidationFailedException e) {
-            assertTrue("Exception not expected: " + e.getMessage(),
-                    e.getErrorCode() == expectedError);
+            assertWithMessage("Exception not expected: %s", e.getMessage()).that(e.getErrorCode())
+                    .isEqualTo(expectedError);
         }
     }
 
@@ -426,8 +429,8 @@
             createPrevFreezePeriod(prevStart, prevEnd, now, dates);
             fail("Invalid period (" + expectedError + ") not flagged: " + String.join(" ", dates));
         } catch (SystemUpdatePolicy.ValidationFailedException e) {
-            assertTrue("Exception not expected: " + e.getMessage(),
-                    e.getErrorCode() == expectedError);
+            assertWithMessage("Exception not expected: %s", e.getMessage()).that(e.getErrorCode())
+                    .isEqualTo(expectedError);
         }
     }
 
@@ -480,7 +483,7 @@
         ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new InputStreamReader(inStream));
-        assertEquals(XmlPullParser.START_TAG, parser.next());
+        assertThat(parser.next()).isEqualTo(XmlPullParser.START_TAG);
         checkFreezePeriods(SystemUpdatePolicy.restoreFromXml(parser), expectedPeriods);
     }
 
@@ -488,8 +491,8 @@
             List<FreezePeriod> expectedPeriods) {
         int i = 0;
         for (FreezePeriod period : policy.getFreezePeriods()) {
-            assertEquals(expectedPeriods.get(i).getStart(), period.getStart());
-            assertEquals(expectedPeriods.get(i).getEnd(), period.getEnd());
+            assertThat(period.getStart()).isEqualTo(expectedPeriods.get(i).getStart());
+            assertThat(period.getEnd()).isEqualTo(expectedPeriods.get(i).getEnd());
             i++;
         }
     }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
index 2005dd9..07ea855 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
@@ -25,14 +25,13 @@
 import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.TAG_TARGET_COMPONENT;
 import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.TAG_USER_ID;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Environment;
-import androidx.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.server.devicepolicy.TransferOwnershipMetadataManager.Injector;
 import com.android.server.devicepolicy.TransferOwnershipMetadataManager.Metadata;
 
@@ -51,12 +50,14 @@
 /**
 * Unit tests for {@link TransferOwnershipMetadataManager}.
  *
- * bit FrameworksServicesTests:com.android.server.devicepolicy.TransferOwnershipMetadataManagerTest
- * runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
-* */
-
+ * <p>Run this test with:
+ *
+ * <pre><code>
+ atest FrameworksServicesTests:com.android.server.devicepolicy.TransferOwnershipMetadataManagerTest
+ * </code></pre>
+ */
 @RunWith(AndroidJUnit4.class)
-public class TransferOwnershipMetadataManagerTest {
+public final class TransferOwnershipMetadataManagerTest {
     private final static String TAG = TransferOwnershipMetadataManagerTest.class.getName();
     private final static String SOURCE_COMPONENT =
             "com.dummy.admin.package/com.dummy.admin.package.SourceClassName";
@@ -77,28 +78,27 @@
     @Test
     public void testSave() {
         TransferOwnershipMetadataManager paramsManager = getOwnerTransferParams();
-        assertTrue(paramsManager.saveMetadataFile(TEST_PARAMS));
-        assertTrue(paramsManager.metadataFileExists());
+        assertThat(paramsManager.saveMetadataFile(TEST_PARAMS)).isTrue();
+        assertThat(paramsManager.metadataFileExists()).isTrue();
     }
 
     @Test
     public void testFileContentValid() {
         TransferOwnershipMetadataManager paramsManager = getOwnerTransferParams();
-        assertTrue(paramsManager.saveMetadataFile(TEST_PARAMS));
+        assertThat(paramsManager.saveMetadataFile(TEST_PARAMS)).isTrue();
         Path path = Paths.get(new File(mMockInjector.getOwnerTransferMetadataDir(),
                 OWNER_TRANSFER_METADATA_XML).getAbsolutePath());
         try {
             String contents = new String(Files.readAllBytes(path), Charset.forName("UTF-8"));
-            assertEquals(
-                "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
-                    + "<" + TAG_USER_ID + ">" + USER_ID + "</" + TAG_USER_ID + ">\n"
-                    + "<" + TAG_SOURCE_COMPONENT + ">" + SOURCE_COMPONENT + "</"
-                        + TAG_SOURCE_COMPONENT + ">\n"
-                    + "<" + TAG_TARGET_COMPONENT + ">" + TARGET_COMPONENT + "</"
-                        + TAG_TARGET_COMPONENT + ">\n"
-                    + "<" + TAG_ADMIN_TYPE + ">" + ADMIN_TYPE_DEVICE_OWNER + "</"
-                        + TAG_ADMIN_TYPE + ">\n",
-                contents);
+            assertThat(contents).isEqualTo(
+                    "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+                            + "<" + TAG_USER_ID + ">" + USER_ID + "</" + TAG_USER_ID + ">\n"
+                            + "<" + TAG_SOURCE_COMPONENT + ">" + SOURCE_COMPONENT + "</"
+                            + TAG_SOURCE_COMPONENT + ">\n"
+                            + "<" + TAG_TARGET_COMPONENT + ">" + TARGET_COMPONENT + "</"
+                            + TAG_TARGET_COMPONENT + ">\n"
+                            + "<" + TAG_ADMIN_TYPE + ">" + ADMIN_TYPE_DEVICE_OWNER + "</"
+                            + TAG_ADMIN_TYPE + ">\n");
         } catch (IOException e) {
             e.printStackTrace();
         }
@@ -124,7 +124,7 @@
             Log.d(TAG, "testLoad: failed to get canonical file");
         }
         paramsManager.saveMetadataFile(TEST_PARAMS);
-        assertEquals(TEST_PARAMS, paramsManager.loadMetadataFile());
+        assertThat(paramsManager.loadMetadataFile()).isEqualTo(TEST_PARAMS);
     }
 
     @Test
@@ -132,7 +132,7 @@
         TransferOwnershipMetadataManager paramsManager = getOwnerTransferParams();
         paramsManager.saveMetadataFile(TEST_PARAMS);
         paramsManager.deleteMetadataFile();
-        assertFalse(paramsManager.metadataFileExists());
+        assertThat(paramsManager.metadataFileExists()).isFalse();
     }
 
     @After
diff --git a/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java
index 56966776..6cea928 100644
--- a/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java
@@ -69,8 +69,7 @@
         MockitoAnnotations.initMocks(this);
 
         mContext = InstrumentationRegistry.getContext();
-        Object lock = new Object();
-        mPermissionManagerService = new PermissionManagerService(mContext, lock, mInjector);
+        mPermissionManagerService = new PermissionManagerService(mContext, mInjector);
     }
 
     @After
diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
index af161ee..ca0270d 100644
--- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
@@ -70,7 +70,6 @@
     private Runnable mOnUserAttention;
     private TestableAttentionDetector mAttentionDetector;
     private AttentionDetector mRealAttentionDetector;
-    private long mPreDimCheckDuration;
     private long mNextDimming;
     private int mIsSettingEnabled;
 
@@ -342,23 +341,14 @@
     public void testGetPostDimCheckDurationMillis_handlesGoodFlagValue() {
         DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
                 KEY_POST_DIM_CHECK_DURATION_MILLIS, "333", false);
-        assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(
-                DEFAULT_DIM_DURATION_MILLIS)).isEqualTo(333);
-    }
-
-    @Test
-    public void testGetPostDimCheckDurationMillis_capsGoodFlagValueByMaxDimDuration() {
-        DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
-                KEY_POST_DIM_CHECK_DURATION_MILLIS, "7000", false);
-        assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(6500)).isEqualTo(6500);
+        assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis()).isEqualTo(333);
     }
 
     @Test
     public void testGetPostDimCheckDurationMillis_rejectsNegativeValue() {
         DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
                 KEY_POST_DIM_CHECK_DURATION_MILLIS, "-50", false);
-        assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(
-                DEFAULT_DIM_DURATION_MILLIS)).isEqualTo(
+        assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis()).isEqualTo(
                 DEFAULT_POST_DIM_CHECK_DURATION_MILLIS);
     }
 
@@ -366,8 +356,7 @@
     public void testGetPostDimCheckDurationMillis_rejectsTooBigValue() {
         DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
                 KEY_POST_DIM_CHECK_DURATION_MILLIS, "20000", false);
-        assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(
-                DEFAULT_DIM_DURATION_MILLIS)).isEqualTo(
+        assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis()).isEqualTo(
                 DEFAULT_POST_DIM_CHECK_DURATION_MILLIS);
     }
 
@@ -375,14 +364,12 @@
     public void testGetPostDimCheckDurationMillis_handlesBadFlagValue() {
         DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
                 KEY_POST_DIM_CHECK_DURATION_MILLIS, "20000k", false);
-        assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(
-                DEFAULT_DIM_DURATION_MILLIS)).isEqualTo(
+        assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis()).isEqualTo(
                 DEFAULT_POST_DIM_CHECK_DURATION_MILLIS);
 
         DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
                 KEY_POST_DIM_CHECK_DURATION_MILLIS, "0.25", false);
-        assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(
-                DEFAULT_DIM_DURATION_MILLIS)).isEqualTo(
+        assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis()).isEqualTo(
                 DEFAULT_POST_DIM_CHECK_DURATION_MILLIS);
     }
 
@@ -423,7 +410,7 @@
     }
 
     private long registerAttention() {
-        mPreDimCheckDuration = 4000L;
+        mAttentionDetector.mPreDimCheckDurationMillis = 4000L;
         mAttentionDetector.onUserActivity(SystemClock.uptimeMillis(),
                 PowerManager.USER_ACTIVITY_EVENT_TOUCH);
         return mAttentionDetector.updateUserActivity(mNextDimming, DEFAULT_DIM_DURATION_MILLIS);
@@ -447,10 +434,5 @@
         public boolean isAttentionServiceSupported() {
             return mAttentionServiceSupported;
         }
-
-        @Override
-        public long getPreDimCheckDurationMillis() {
-            return mPreDimCheckDuration;
-        }
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index b4480ae..f1d49d5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -976,6 +976,21 @@
         });
     }
 
+    @Test
+    public void testReparentToOrganizedTask() {
+        final ITaskOrganizer organizer = registerMockOrganizer();
+        Task rootTask = mWm.mAtmService.mTaskOrganizerController.createRootTask(
+                mDisplayContent, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, null);
+        final Task task1 = createStack();
+        final Task task2 = createTask(rootTask, false /* fakeDraw */);
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        wct.reparent(task1.mRemoteToken.toWindowContainerToken(),
+                rootTask.mRemoteToken.toWindowContainerToken(), true /* onTop */);
+        mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
+        assertTrue(task1.isOrganized());
+        assertTrue(task2.isOrganized());
+    }
+
     /**
      * Verifies that task vanished is called for a specific task.
      */
diff --git a/wifi/aidl-export/android/net/wifi/aware/AwareResources.aidl b/wifi/aidl-export/android/net/wifi/aware/AwareResources.aidl
new file mode 100644
index 0000000..d0bd2dd
--- /dev/null
+++ b/wifi/aidl-export/android/net/wifi/aware/AwareResources.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 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.net.wifi.aware;
+
+parcelable AwareResources;
\ No newline at end of file
diff --git a/wifi/api/current.txt b/wifi/api/current.txt
index 0bc1ff2..d5ef703 100644
--- a/wifi/api/current.txt
+++ b/wifi/api/current.txt
@@ -561,6 +561,15 @@
     method public void onAttached(android.net.wifi.aware.WifiAwareSession);
   }
 
+  public final class AwareResources implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getNumOfAvailableDataPaths();
+    method public int getNumOfAvailablePublishSessions();
+    method public int getNumOfAvailableSubscribeSessions();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.AwareResources> CREATOR;
+  }
+
   public final class Characteristics implements android.os.Parcelable {
     method public int describeContents();
     method public int getMaxMatchFilterLength();
@@ -663,7 +672,8 @@
   public class WifiAwareManager {
     method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @Nullable android.os.Handler);
     method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @NonNull android.net.wifi.aware.IdentityChangedListener, @Nullable android.os.Handler);
-    method public android.net.wifi.aware.Characteristics getCharacteristics();
+    method @Nullable public android.net.wifi.aware.AwareResources getAvailableAwareResources();
+    method @Nullable public android.net.wifi.aware.Characteristics getCharacteristics();
     method public boolean isAvailable();
     method public boolean isDeviceAttached();
     method public boolean isInstantCommunicationModeEnabled();
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index fa99da7..edbd463 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -428,8 +428,11 @@
     method public double getSuccessfulRxPacketsPerSecond();
     method public double getSuccessfulTxPacketsPerSecond();
     method public boolean isEphemeral();
+    method public boolean isOemPaid();
+    method public boolean isOemPrivate();
     method public boolean isOsuAp();
     method public boolean isPasspointAp();
+    method public boolean isTrusted();
     method @Nullable public static String sanitizeSsid(@Nullable String);
     field public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
     field public static final int INVALID_RSSI = -127; // 0xffffff81
@@ -618,11 +621,13 @@
   public final class WifiNetworkSuggestion implements android.os.Parcelable {
     method @NonNull public android.net.wifi.WifiConfiguration getWifiConfiguration();
     method public boolean isOemPaid();
+    method public boolean isOemPrivate();
   }
 
   public static final class WifiNetworkSuggestion.Builder {
     method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) public android.net.wifi.WifiNetworkSuggestion.Builder setCarrierId(int);
     method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setOemPaid(boolean);
+    method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setOemPrivate(boolean);
   }
 
   public class WifiScanner {
diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt
index b0ff4bb..ff06a18 100644
--- a/wifi/jarjar-rules.txt
+++ b/wifi/jarjar-rules.txt
@@ -36,7 +36,7 @@
 rule android.net.ipmemorystore.NetworkAttributesParcelable* com.android.wifi.x.@0
 rule android.net.ipmemorystore.SameL3NetworkResponseParcelable* com.android.wifi.x.@0
 rule android.net.ipmemorystore.StatusParcelable* com.android.wifi.x.@0
-rule android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirk* com.android.wifi.x.@0
+rule android.net.networkstack.aidl.** com.android.wifi.x.@0
 
 # Net utils (includes Network Stack helper classes).
 rule android.net.DhcpResults* com.android.wifi.x.@0
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 9ca64d2..8103ff7 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1011,6 +1011,17 @@
      */
     public boolean oemPaid;
 
+
+    /**
+     * Indicate whether the network is oem private or not. Networks are considered oem private
+     * if the corresponding connection is only available to system apps.
+     *
+     * This bit can only be used by suggestion network, see
+     * {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)}
+     * @hide
+     */
+    public boolean oemPrivate;
+
     /**
      * True if this Wifi configuration is created from a {@link WifiNetworkSuggestion},
      * false otherwise.
@@ -2249,6 +2260,7 @@
         osu = false;
         trusted = true; // Networks are considered trusted by default.
         oemPaid = false;
+        oemPrivate = false;
         fromWifiNetworkSuggestion = false;
         fromWifiNetworkSpecifier = false;
         meteredHint = false;
@@ -2372,13 +2384,14 @@
         if (this.osu) sbuf.append(" osu");
         if (this.trusted) sbuf.append(" trusted");
         if (this.oemPaid) sbuf.append(" oemPaid");
+        if (this.oemPrivate) sbuf.append(" oemPrivate");
         if (this.fromWifiNetworkSuggestion) sbuf.append(" fromWifiNetworkSuggestion");
         if (this.fromWifiNetworkSpecifier) sbuf.append(" fromWifiNetworkSpecifier");
         if (this.meteredHint) sbuf.append(" meteredHint");
         if (this.useExternalScores) sbuf.append(" useExternalScores");
         if (this.validatedInternetAccess || this.ephemeral || this.trusted || this.oemPaid
-                || this.fromWifiNetworkSuggestion || this.fromWifiNetworkSpecifier
-                || this.meteredHint || this.useExternalScores) {
+                || this.oemPrivate || this.fromWifiNetworkSuggestion
+                || this.fromWifiNetworkSpecifier || this.meteredHint || this.useExternalScores) {
             sbuf.append("\n");
         }
         if (this.meteredOverride != METERED_OVERRIDE_NONE) {
@@ -2943,6 +2956,7 @@
             osu = source.osu;
             trusted = source.trusted;
             oemPaid = source.oemPaid;
+            oemPrivate = source.oemPrivate;
             fromWifiNetworkSuggestion = source.fromWifiNetworkSuggestion;
             fromWifiNetworkSpecifier = source.fromWifiNetworkSpecifier;
             meteredHint = source.meteredHint;
@@ -3024,6 +3038,7 @@
         dest.writeInt(ephemeral ? 1 : 0);
         dest.writeInt(trusted ? 1 : 0);
         dest.writeInt(oemPaid ? 1 : 0);
+        dest.writeInt(oemPrivate ? 1 : 0);
         dest.writeInt(fromWifiNetworkSuggestion ? 1 : 0);
         dest.writeInt(fromWifiNetworkSpecifier ? 1 : 0);
         dest.writeInt(meteredHint ? 1 : 0);
@@ -3102,6 +3117,7 @@
                 config.ephemeral = in.readInt() != 0;
                 config.trusted = in.readInt() != 0;
                 config.oemPaid = in.readInt() != 0;
+                config.oemPrivate = in.readInt() != 0;
                 config.fromWifiNetworkSuggestion =  in.readInt() != 0;
                 config.fromWifiNetworkSpecifier =  in.readInt() != 0;
                 config.meteredHint = in.readInt() != 0;
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index fe5002e..774c043 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -164,6 +164,11 @@
     private boolean mOemPaid;
 
     /**
+     * Whether the network is oem private or not.
+     */
+    private boolean mOemPrivate;
+
+    /**
      * OSU (Online Sign Up) AP for Passpoint R2.
      */
     private boolean mOsuAp;
@@ -327,6 +332,9 @@
         setFrequency(-1);
         setMeteredHint(false);
         setEphemeral(false);
+        setTrusted(false);
+        setOemPaid(false);
+        setOemPrivate(false);
         setOsuAp(false);
         setRequestingPackageName(null);
         setFQDN(null);
@@ -363,7 +371,8 @@
             mMeteredHint = source.mMeteredHint;
             mEphemeral = source.mEphemeral;
             mTrusted = source.mTrusted;
-            mTrusted = source.mOemPaid;
+            mOemPaid = source.mOemPaid;
+            mOemPrivate = source.mOemPrivate;
             mRequestingPackageName =
                     source.mRequestingPackageName;
             mOsuAp = source.mOsuAp;
@@ -722,7 +731,12 @@
         mTrusted = trusted;
     }
 
-    /** {@hide} */
+    /**
+     * Returns true if the current Wifi network is a trusted network, false otherwise.
+     * @see WifiNetworkSuggestion.Builder#setUntrusted(boolean).
+     * {@hide}
+     */
+    @SystemApi
     public boolean isTrusted() {
         return mTrusted;
     }
@@ -732,12 +746,32 @@
         mOemPaid = oemPaid;
     }
 
-    /** {@hide} */
+    /**
+     * Returns true if the current Wifi network is an oem paid network, false otherwise.
+     * @see WifiNetworkSuggestion.Builder#setOemPaid(boolean).
+     * {@hide}
+     */
+    @SystemApi
     public boolean isOemPaid() {
         return mOemPaid;
     }
 
     /** {@hide} */
+    public void setOemPrivate(boolean oemPrivate) {
+        mOemPrivate = oemPrivate;
+    }
+
+    /**
+     * Returns true if the current Wifi network is an oem private network, false otherwise.
+     * @see WifiNetworkSuggestion.Builder#setOemPrivate(boolean).
+     * {@hide}
+     */
+    @SystemApi
+    public boolean isOemPrivate() {
+        return mOemPrivate;
+    }
+
+    /** {@hide} */
     public void setOsuAp(boolean osuAp) {
         mOsuAp = osuAp;
     }
@@ -975,6 +1009,7 @@
         dest.writeInt(mEphemeral ? 1 : 0);
         dest.writeInt(mTrusted ? 1 : 0);
         dest.writeInt(mOemPaid ? 1 : 0);
+        dest.writeInt(mOemPrivate ? 1 : 0);
         dest.writeInt(score);
         dest.writeLong(txSuccess);
         dest.writeDouble(mSuccessfulTxPacketsPerSecond);
@@ -1021,6 +1056,7 @@
                 info.mEphemeral = in.readInt() != 0;
                 info.mTrusted = in.readInt() != 0;
                 info.mOemPaid = in.readInt() != 0;
+                info.mOemPrivate = in.readInt() != 0;
                 info.score = in.readInt();
                 info.txSuccess = in.readLong();
                 info.mSuccessfulTxPacketsPerSecond = in.readDouble();
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index acae218..dc6ec90 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -25,6 +25,7 @@
 import android.annotation.SystemApi;
 import android.net.MacAddress;
 import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -180,6 +181,12 @@
         private boolean mIsNetworkOemPaid;
 
         /**
+         * Whether this network will be brought up as OEM private (OEM_PRIVATE capability bit
+         * added).
+         */
+        private boolean mIsNetworkOemPrivate;
+
+        /**
          * Whether this network will use enhanced MAC randomization.
          */
         private boolean mIsEnhancedMacRandomizationEnabled;
@@ -206,6 +213,7 @@
             mWapiEnterpriseConfig = null;
             mIsNetworkUntrusted = false;
             mIsNetworkOemPaid = false;
+            mIsNetworkOemPrivate = false;
             mPriorityGroup = 0;
             mIsEnhancedMacRandomizationEnabled = false;
             mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -667,6 +675,9 @@
          * reduce it). The connectivity service may use this information to influence the overall
          * network configuration of the device.
          * <p>
+         * <li> These suggestions are only considered for network selection if a
+         * {@link NetworkRequest} without {@link NetworkCapabilities#NET_CAPABILITY_TRUSTED}
+         * capability is filed.
          * <li> An untrusted network's credentials may not be shared with the user using
          * {@link #setCredentialSharedWithUser(boolean)}.</li>
          * <li> If not set, defaults to false (i.e. network is trusted).</li>
@@ -688,7 +699,7 @@
          * <li>The connectivity service may use this information to influence the overall
          * network configuration of the device. This network is typically only available to system
          * apps.
-         * <li>On devices which support only 1 concurrent connection (indicated via
+         * <li>On devices which do not support concurrent connection (indicated via
          * {@link WifiManager#isMultiStaConcurrencySupported()}, Wi-Fi network selection process may
          * use this information to influence priority of the suggested network for Wi-Fi network
          * selection (most likely to reduce it).
@@ -699,6 +710,13 @@
          * <p>
          * <li> An OEM paid network's credentials may not be shared with the user using
          * {@link #setCredentialSharedWithUser(boolean)}.</li>
+         * <li> These suggestions are only considered for network selection if a
+         * {@link NetworkRequest} with {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}
+         * capability is filed.
+         * <li> Each suggestion can have both {@link #setOemPaid(boolean)} and
+         * {@link #setOemPrivate(boolean)} set if the app wants these suggestions considered
+         * for creating either an OEM paid network or OEM private network determined based on
+         * the {@link NetworkRequest} that is active.
          * <li> If not set, defaults to false (i.e. network is not OEM paid).</li>
          *
          * @param isOemPaid Boolean indicating whether the network should be brought up as OEM paid
@@ -715,6 +733,48 @@
             return this;
         }
 
+        /**
+         * Specifies whether the system will bring up the network (if selected) as OEM private. An
+         * OEM private network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE} capability
+         * added.
+         * Note:
+         * <li>The connectivity service may use this information to influence the overall
+         * network configuration of the device. This network is typically only available to system
+         * apps.
+         * <li>On devices which do not support concurrent connection (indicated via
+         * {@link WifiManager#isMultiStaConcurrencySupported()}, Wi-Fi network selection process may
+         * use this information to influence priority of the suggested network for Wi-Fi network
+         * selection (most likely to reduce it).
+         * <li>On devices which support more than 1 concurrent connections (indicated via
+         * {@link WifiManager#isMultiStaConcurrencySupported()}, these OEM private networks will be
+         * brought up as a secondary concurrent connection (primary connection will be used
+         * for networks available to the user and all apps.
+         * <p>
+         * <li> An OEM private network's credentials may not be shared with the user using
+         * {@link #setCredentialSharedWithUser(boolean)}.</li>
+         * <li> These suggestions are only considered for network selection if a
+         * {@link NetworkRequest} with {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}
+         * capability is filed.
+         * <li> Each suggestion can have both {@link #setOemPaid(boolean)} and
+         * {@link #setOemPrivate(boolean)} set if the app wants these suggestions considered
+         * for creating either an OEM paid network or OEM private network determined based on
+         * the {@link NetworkRequest} that is active.
+         * <li> If not set, defaults to false (i.e. network is not OEM private).</li>
+         *
+         * @param isOemPrivate Boolean indicating whether the network should be brought up as OEM
+         *                     private (if true) or not OEM private (if false).
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         * @hide
+         */
+        @SystemApi
+        public @NonNull Builder setOemPrivate(boolean isOemPrivate) {
+            if (!SdkLevel.isAtLeastS()) {
+                throw new UnsupportedOperationException();
+            }
+            mIsNetworkOemPrivate = isOemPrivate;
+            return this;
+        }
+
         private void setSecurityParamsInWifiConfiguration(
                 @NonNull WifiConfiguration configuration) {
             if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network.
@@ -786,6 +846,7 @@
             wifiConfiguration.carrierId = mCarrierId;
             wifiConfiguration.trusted = !mIsNetworkUntrusted;
             wifiConfiguration.oemPaid = mIsNetworkOemPaid;
+            wifiConfiguration.oemPrivate = mIsNetworkOemPrivate;
             wifiConfiguration.macRandomizationSetting = mIsEnhancedMacRandomizationEnabled
                     ? WifiConfiguration.RANDOMIZATION_ENHANCED
                     : WifiConfiguration.RANDOMIZATION_PERSISTENT;
@@ -819,6 +880,7 @@
             wifiConfiguration.meteredOverride = mMeteredOverride;
             wifiConfiguration.trusted = !mIsNetworkUntrusted;
             wifiConfiguration.oemPaid = mIsNetworkOemPaid;
+            wifiConfiguration.oemPrivate = mIsNetworkOemPrivate;
             wifiConfiguration.subscriptionId = mSubscriptionId;
             mPasspointConfiguration.setCarrierId(mCarrierId);
             mPasspointConfiguration.setSubscriptionId(mSubscriptionId);
@@ -938,6 +1000,14 @@
                 }
                 mIsSharedWithUser = false;
             }
+            if (mIsNetworkOemPrivate) {
+                if (mIsSharedWithUserSet && mIsSharedWithUser) {
+                    throw new IllegalStateException("Should not be both"
+                            + "setCredentialSharedWithUser and +"
+                            + "setOemPrivate to true");
+                }
+                mIsSharedWithUser = false;
+            }
             return new WifiNetworkSuggestion(
                     wifiConfiguration,
                     mPasspointConfiguration,
@@ -1105,6 +1175,7 @@
                 .append(", isInitialAutoJoinEnabled=").append(isInitialAutoJoinEnabled)
                 .append(", isUnTrusted=").append(!wifiConfiguration.trusted)
                 .append(", isOemPaid=").append(wifiConfiguration.oemPaid)
+                .append(", isOemPrivate=").append(wifiConfiguration.oemPrivate)
                 .append(", priorityGroup=").append(priorityGroup)
                 .append(" ]");
         return sb.toString();
@@ -1212,6 +1283,18 @@
     }
 
     /**
+     * @see Builder#setOemPrivate(boolean)
+     * @hide
+     */
+    @SystemApi
+    public boolean isOemPrivate() {
+        if (!SdkLevel.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        return wifiConfiguration.oemPrivate;
+    }
+
+    /**
      * Get the WifiEnterpriseConfig, or null if unset.
      * @see Builder#setWapiEnterpriseConfig(WifiEnterpriseConfig)
      * @see Builder#setWpa2EnterpriseConfig(WifiEnterpriseConfig)
diff --git a/wifi/java/android/net/wifi/aware/AwareResources.java b/wifi/java/android/net/wifi/aware/AwareResources.java
new file mode 100644
index 0000000..cee1f40
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/AwareResources.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2020 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.net.wifi.aware;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * The resources of the Aware service.
+ */
+public final class AwareResources implements Parcelable {
+    /**
+     * Number of the NDPs are available.
+     */
+    private int mNumOfAvailableNdps;
+
+    /**
+     * Number of the publish sessions are available.
+     */
+    private int mNumOfAvailablePublishSessions;
+
+    /**
+     * Number of the subscribe sessions are available.
+     */
+    private int mNumOfAvailableSubscribeSessions;
+
+    /**
+     * @hide : should not be created by apps
+     */
+    public AwareResources() {
+    }
+
+    /**
+     * Return the number of Aware data-paths (also known as NDPs - NAN Data Paths) which an app
+     * could create. Please refer to the {@link WifiAwareNetworkSpecifier} to create
+     * a Network Specifier and request a data-path.
+     * <p>
+     * Note that these resources aren't reserved - other apps could use them by the time you
+     * attempt to create a data-path.
+     * </p>
+     * @return A Non-negative integer, number of data-paths that could be created.
+     */
+    public int getNumOfAvailableDataPaths() {
+        return mNumOfAvailableNdps;
+    }
+
+    /**
+     * Return the number of Aware publish sessions which an app could create. Please refer to the
+     * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)}
+     * to create a publish session.
+     * <p>
+     * Note that these resources aren't reserved - other apps could use them by the time you
+     * attempt to create a publish session.
+     * </p>
+     * @return A Non-negative integer, number of publish sessions that could be created.
+     */
+    public int getNumOfAvailablePublishSessions() {
+        return mNumOfAvailablePublishSessions;
+    }
+
+    /**
+     * Return the number of Aware subscribe sessions which an app could create. Please refer to the
+     * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, Handler)}
+     * to create a publish session.
+     * <p>
+     * Note that these resources aren't reserved - other apps could use them by the time you
+     * attempt to create a subscribe session.
+     * </p>
+     * @return A Non-negative integer, number of subscribe sessions that could be created.
+     */
+    public int getNumOfAvailableSubscribeSessions() {
+        return mNumOfAvailableSubscribeSessions;
+    }
+
+    /**
+     * Set the number of the available NDPs.
+     * @hide
+     * @param numOfAvailableNdps Number of available NDPs.
+     */
+    public void setNumOfAvailableDataPaths(int numOfAvailableNdps) {
+        mNumOfAvailableNdps = numOfAvailableNdps;
+    }
+
+    /**
+     * Set the number of the available publish sessions.
+     * @hide
+     * @param numOfAvailablePublishSessions Number of available publish sessions.
+     */
+    public void setNumOfAvailablePublishSessions(int numOfAvailablePublishSessions) {
+        mNumOfAvailablePublishSessions = numOfAvailablePublishSessions;
+    }
+
+    /**
+     * Set the number of the available subscribe sessions.
+     * @hide
+     * @param numOfAvailableSubscribeSessions Number of available subscribe sessions.
+     */
+    public void setNumOfAvailableSubscribeSessions(int numOfAvailableSubscribeSessions) {
+        mNumOfAvailableSubscribeSessions = numOfAvailableSubscribeSessions;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mNumOfAvailableNdps);
+        dest.writeInt(mNumOfAvailablePublishSessions);
+        dest.writeInt(mNumOfAvailableSubscribeSessions);
+    }
+
+    public static final @android.annotation.NonNull Creator<AwareResources> CREATOR =
+            new Creator<AwareResources>() {
+                @Override
+                public AwareResources createFromParcel(Parcel in) {
+                    AwareResources awareResources = new AwareResources();
+                    awareResources.setNumOfAvailableDataPaths(in.readInt());
+                    awareResources.setNumOfAvailablePublishSessions(in.readInt());
+                    awareResources.setNumOfAvailableSubscribeSessions(in.readInt());
+                    return awareResources;
+                }
+
+                @Override
+                public AwareResources[] newArray(int size) {
+                    return new AwareResources[size];
+                }
+            };
+}
diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
index cd2ca69..c90c4d8 100644
--- a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
@@ -25,6 +25,7 @@
 import android.net.wifi.aware.PublishConfig;
 import android.net.wifi.aware.SubscribeConfig;
 import android.net.wifi.aware.Characteristics;
+import android.net.wifi.aware.AwareResources;
 
 /**
  * Interface that WifiAwareService implements
@@ -36,6 +37,7 @@
     // Aware API
     boolean isUsageEnabled();
     Characteristics getCharacteristics();
+    AwareResources getAvailableAwareResources();
     boolean isDeviceAttached();
     void enableInstantCommunicationMode(in String callingPackage, boolean enable);
     boolean isInstantCommunicationModeEnabled();
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 67c6032..e19b095 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -263,7 +263,7 @@
      *
      * @return An object specifying configuration limitations of Aware.
      */
-    public Characteristics getCharacteristics() {
+    public @Nullable Characteristics getCharacteristics() {
         try {
             return mService.getCharacteristics();
         } catch (RemoteException e) {
@@ -272,6 +272,23 @@
     }
 
     /**
+     * Return the available resources of the Wi-Fi aware service: a set of parameters which specify
+     * limitations on service usage, e.g the number of data-paths which could be created..
+     *
+     * @return An object specifying the currently available resource of the Wi-Fi Aware service.
+     */
+    public @Nullable AwareResources getAvailableAwareResources() {
+        if (!SdkLevel.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        try {
+            return mService.getAvailableAwareResources();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Attach to the Wi-Fi Aware service - enabling the application to create discovery sessions or
      * create connections to peers. The device will attach to an existing cluster if it can find
      * one or create a new cluster (if it is the first to enable Aware in its vicinity). Results
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index b82c67b..f09c37d 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -69,6 +69,7 @@
         config.setPasspointManagementObjectTree(cookie);
         config.trusted = false;
         config.oemPaid = true;
+        config.oemPrivate = true;
         config.updateIdentifier = "1234";
         config.fromWifiNetworkSpecifier = true;
         config.fromWifiNetworkSuggestion = true;
@@ -91,8 +92,10 @@
         assertEquals(macBeforeParcel, reconfig.getRandomizedMacAddress());
         assertEquals(config.updateIdentifier, reconfig.updateIdentifier);
         assertFalse(reconfig.trusted);
-        assertTrue(config.fromWifiNetworkSpecifier);
-        assertTrue(config.fromWifiNetworkSuggestion);
+        assertTrue(reconfig.fromWifiNetworkSpecifier);
+        assertTrue(reconfig.fromWifiNetworkSuggestion);
+        assertTrue(reconfig.oemPaid);
+        assertTrue(reconfig.oemPrivate);
 
         Parcel parcelWW = Parcel.obtain();
         reconfig.writeToParcel(parcelWW, 0);
@@ -103,6 +106,32 @@
     }
 
     @Test
+    public void testWifiConfigurationCopyConstructor() {
+        WifiConfiguration config = new WifiConfiguration();
+        config.trusted = false;
+        config.oemPaid = true;
+        config.oemPrivate = true;
+        config.updateIdentifier = "1234";
+        config.fromWifiNetworkSpecifier = true;
+        config.fromWifiNetworkSuggestion = true;
+        config.setRandomizedMacAddress(MacAddressUtils.createRandomUnicastAddress());
+        MacAddress macBeforeParcel = config.getRandomizedMacAddress();
+        config.subscriptionId = 1;
+        config.carrierId = 1189;
+
+        WifiConfiguration reconfig = new WifiConfiguration(config);
+
+        // lacking a useful config.equals, check two fields near the end.
+        assertEquals(macBeforeParcel, reconfig.getRandomizedMacAddress());
+        assertEquals(config.updateIdentifier, reconfig.updateIdentifier);
+        assertFalse(reconfig.trusted);
+        assertTrue(reconfig.fromWifiNetworkSpecifier);
+        assertTrue(reconfig.fromWifiNetworkSuggestion);
+        assertTrue(reconfig.oemPaid);
+        assertTrue(reconfig.oemPrivate);
+    }
+
+    @Test
     public void testIsOpenNetwork_IsOpen_NullWepKeys() {
         WifiConfiguration config = new WifiConfiguration();
         config.allowedKeyManagement.clear();
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
index 06ae13a..c6faf66 100644
--- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -17,6 +17,7 @@
 package android.net.wifi;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
@@ -62,6 +63,7 @@
         writeWifiInfo.rxSuccess = TEST_RX_SUCCESS;
         writeWifiInfo.setTrusted(true);
         writeWifiInfo.setOemPaid(true);
+        writeWifiInfo.setOemPrivate(true);
         writeWifiInfo.setOsuAp(true);
         writeWifiInfo.setFQDN(TEST_FQDN);
         writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
@@ -83,6 +85,46 @@
         assertEquals(TEST_RX_SUCCESS, readWifiInfo.rxSuccess);
         assertTrue(readWifiInfo.isTrusted());
         assertTrue(readWifiInfo.isOemPaid());
+        assertTrue(readWifiInfo.isOemPrivate());
+        assertTrue(readWifiInfo.isOsuAp());
+        assertTrue(readWifiInfo.isPasspointAp());
+        assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getRequestingPackageName());
+        assertEquals(TEST_FQDN, readWifiInfo.getPasspointFqdn());
+        assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getPasspointProviderFriendlyName());
+        assertEquals(TEST_WIFI_STANDARD, readWifiInfo.getWifiStandard());
+        assertEquals(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS,
+                readWifiInfo.getMaxSupportedTxLinkSpeedMbps());
+        assertEquals(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS,
+                readWifiInfo.getMaxSupportedRxLinkSpeedMbps());
+    }
+
+    @Test
+    public void testWifiInfoCopyConstructor() throws Exception {
+        WifiInfo writeWifiInfo = new WifiInfo();
+        writeWifiInfo.txSuccess = TEST_TX_SUCCESS;
+        writeWifiInfo.txRetries = TEST_TX_RETRIES;
+        writeWifiInfo.txBad = TEST_TX_BAD;
+        writeWifiInfo.rxSuccess = TEST_RX_SUCCESS;
+        writeWifiInfo.setTrusted(true);
+        writeWifiInfo.setOemPaid(true);
+        writeWifiInfo.setOemPrivate(true);
+        writeWifiInfo.setOsuAp(true);
+        writeWifiInfo.setFQDN(TEST_FQDN);
+        writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
+        writeWifiInfo.setRequestingPackageName(TEST_PACKAGE_NAME);
+        writeWifiInfo.setWifiStandard(TEST_WIFI_STANDARD);
+        writeWifiInfo.setMaxSupportedTxLinkSpeedMbps(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS);
+        writeWifiInfo.setMaxSupportedRxLinkSpeedMbps(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS);
+
+        WifiInfo readWifiInfo = new WifiInfo(writeWifiInfo);
+
+        assertEquals(TEST_TX_SUCCESS, readWifiInfo.txSuccess);
+        assertEquals(TEST_TX_RETRIES, readWifiInfo.txRetries);
+        assertEquals(TEST_TX_BAD, readWifiInfo.txBad);
+        assertEquals(TEST_RX_SUCCESS, readWifiInfo.rxSuccess);
+        assertTrue(readWifiInfo.isTrusted());
+        assertTrue(readWifiInfo.isOemPaid());
+        assertTrue(readWifiInfo.isOemPrivate());
         assertTrue(readWifiInfo.isOsuAp());
         assertTrue(readWifiInfo.isPasspointAp());
         assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getRequestingPackageName());
@@ -110,6 +152,8 @@
         assertEquals(WifiManager.UNKNOWN_SSID, wifiInfo.getSSID());
         assertEquals(null, wifiInfo.getBSSID());
         assertEquals(-1, wifiInfo.getNetworkId());
+        assertFalse(wifiInfo.isOemPaid());
+        assertFalse(wifiInfo.isOemPrivate());
     }
 
     /**
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 56e7998..870ff0a 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -223,6 +223,34 @@
 
     /**
      * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkSuggestion.Builder#build()} for OWE network.
+     */
+    @Test
+    public void testWifiNetworkSuggestionBuilderForOemPrivateEnhancedOpenNetworkWithBssid() {
+        assumeTrue(SdkLevel.isAtLeastS());
+
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setBssid(MacAddress.fromString(TEST_BSSID))
+                .setOemPrivate(true)
+                .setIsEnhancedOpen(true)
+                .build();
+
+        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+        assertEquals(TEST_BSSID, suggestion.wifiConfiguration.BSSID);
+        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.OWE));
+        assertNull(suggestion.wifiConfiguration.preSharedKey);
+        assertTrue(suggestion.wifiConfiguration.requirePmf);
+        assertTrue(suggestion.wifiConfiguration.oemPrivate);
+        assertTrue(suggestion.isOemPrivate());
+        assertFalse(suggestion.isUserAllowedToManuallyConnect);
+        assertTrue(suggestion.isInitialAutoJoinEnabled);
+        assertNull(suggestion.getEnterpriseConfig());
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSuggestion object created by
      * {@link WifiNetworkSuggestion.Builder#build()} for SAE network.
      */
     @Test
@@ -1285,6 +1313,41 @@
     }
 
     /**
+     * Validate {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} set the
+     * correct value to the WifiConfiguration.
+     */
+    @Test
+    public void testSetIsNetworkAsOemPrivate() {
+        assumeTrue(SdkLevel.isAtLeastS());
+
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setWpa2Passphrase(TEST_PRESHARED_KEY)
+                .setOemPrivate(true)
+                .build();
+        assertTrue(suggestion.isOemPrivate());
+        assertFalse(suggestion.isUserAllowedToManuallyConnect);
+    }
+
+    /**
+     * Validate {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} set the
+     * correct value to the WifiConfiguration.
+     * Also the {@link WifiNetworkSuggestion#isUserAllowedToManuallyConnect} should be false;
+     */
+    @Test
+    public void testSetIsNetworkAsOemPrivateOnPasspointNetwork() {
+        assumeTrue(SdkLevel.isAtLeastS());
+
+        PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setPasspointConfig(passpointConfiguration)
+                .setOemPrivate(true)
+                .build();
+        assertTrue(suggestion.isOemPrivate());
+        assertFalse(suggestion.isUserAllowedToManuallyConnect);
+    }
+
+    /**
      * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
      * when set {@link WifiNetworkSuggestion.Builder#setUntrusted(boolean)} to true and
      * set {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} to true
@@ -1320,6 +1383,24 @@
 
     /**
      * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when set {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)} to true and
+     * set {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} to true
+     * together.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testSetCredentialSharedWithUserWithSetIsNetworkAsOemPrivate() {
+        assumeTrue(SdkLevel.isAtLeastS());
+
+        new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setWpa2Passphrase(TEST_PRESHARED_KEY)
+                .setCredentialSharedWithUser(true)
+                .setOemPrivate(true)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
      * when set both {@link WifiNetworkSuggestion.Builder#setIsInitialAutojoinEnabled(boolean)}
      * and {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} (boolean)}
      * to false on a passpoint suggestion.
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index d0d0c57..1ecd325 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -155,6 +155,7 @@
      */
     @Test
     public void testIsAttached() throws Exception {
+        assumeTrue(SdkLevel.isAtLeastS());
         mDut.isDeviceAttached();
         verify(mockAwareService).isDeviceAttached();
     }
@@ -172,6 +173,16 @@
         verify(mockAwareService).enableInstantCommunicationMode(anyString(), eq(true));
     }
 
+    /**
+     * Validate pass-through of getAvailableAwareResources() API.
+     */
+    @Test
+    public void testGetAvailableAwareResource() throws Exception {
+        assumeTrue(SdkLevel.isAtLeastS());
+        mDut.getAvailableAwareResources();
+        verify(mockAwareService).getAvailableAwareResources();
+    }
+
     /*
      * WifiAwareEventCallbackProxy Tests
      */